java編程中,常常會利用Executors的newXXXThreasPool生成各類線程池,今天寫了一小段代碼,簡單測試了下三種經常使用的線程池:java
import com.google.common.util.concurrent.ThreadFactoryBuilder; import java.util.ArrayList; import java.util.List; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; /** * 測試類(由於要用到forkjoin框架,因此得繼承自RecursiveXXX) */ public class MathTest extends RecursiveAction { private List<Integer> target; private static AtomicInteger count = new AtomicInteger(0); public MathTest(List<Integer> list) { this.target = list; } public double process(Integer d) { //模擬處理數據耗時200ms try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } //System.out.println("thread:" + Thread.currentThread().getId() + "-" + Thread.currentThread().getName() + ", d: " + d); return d; } @Override protected void compute() { if (target.size() <= 2) { for (Integer d : target) { process(d); count.incrementAndGet(); } return; } int mid = target.size() / 2; MathTest t1 = new MathTest(target.subList(0, mid)); MathTest t2 = new MathTest(target.subList(mid, target.size())); t1.fork(); t2.fork(); } public static void main(String[] args) { int num = 100; int threadCount = 4; List<Integer> target = new ArrayList<>(num); for (int i = 0; i < num; i++) { target.add(i); } MathTest test = new MathTest(target); //原始方法,單線程跑 long start = System.currentTimeMillis(); for (int i = 0; i < target.size(); i++) { test.process(target.get(i)); } long end = System.currentTimeMillis(); System.out.println("原始方法耗時:" + (end - start) + "\n"); //固定線程池 final ThreadFactory fixedFactory = new ThreadFactoryBuilder().setNameFormat("fixed-%d").build(); ExecutorService service = Executors.newFixedThreadPool(threadCount, fixedFactory); count.set(0); start = System.currentTimeMillis(); for (Integer d : target) { service.submit(() -> { test.process(d); count.incrementAndGet(); }); } while (true) { if (count.get() >= target.size()) { end = System.currentTimeMillis(); System.out.println("fixedThreadPool耗時:" + (end - start) + "\n"); break; } } //cached線程池 final ThreadFactory cachedFactory = new ThreadFactoryBuilder().setNameFormat("cached-%d").build(); service = Executors.newCachedThreadPool(cachedFactory); count.set(0); start = System.currentTimeMillis(); for (Integer d : target) { service.submit(() -> { test.process(d); count.incrementAndGet(); }); } while (true) { if (count.get() >= target.size()) { end = System.currentTimeMillis(); System.out.println("cachedThreadPool耗時:" + (end - start) + "\n"); break; } } //newWorkStealing線程池 service = Executors.newWorkStealingPool(threadCount); count.set(0); start = System.currentTimeMillis(); for (Integer d : target) { service.submit(() -> { test.process(d); count.incrementAndGet(); }); } while (true) { if (count.get() >= target.size()) { end = System.currentTimeMillis(); System.out.println("workStealingPool耗時:" + (end - start) + "\n"); break; } } //forkJoinPool ForkJoinPool forkJoinPool = new ForkJoinPool(threadCount); count.set(0); start = System.currentTimeMillis(); forkJoinPool.submit(test); while (true) { if (count.get() >= target.size()) { end = System.currentTimeMillis(); System.out.println("forkJoinPool耗時:" + (end - start) + "\n"); break; } } } }
代碼很簡單,就是給一個List,而後對裏面的每一個元素作處理(process方法),用三種線程池分別跑了一下,最後看耗時,輸出以下:編程
原始方法耗時:20156 fixedThreadPool耗時:5145 cachedThreadPool耗時:228 workStealingPool耗時:5047 forkJoinPool耗時:5042
環境:mac + intel i5(虛擬4核)。 workStealingPool內部其實就是ForkJoin框架,因此兩者在耗時上基本同樣,符合預期;若是業務的處理時間較短,從測試結果來看,cachedThreadPool最快。框架