-
爲什麼要用線程池
1.降低資源消耗:通過重用已經創建的線程來降低線程創建和銷燬的消耗
2.提高響應速度:任務到達時不需要等待線程創建就可以立即執行
3.提高線程的可管理性:線程池可以統一管理、分配、調優和監控 -
線程的四種創建方式
1.Executors.newFixedThreadPool 創建一個coreSize=maxSize=n的線程池,每個線程不限制空閒時間,一直阻塞等待任務(LinkedBlockingQueue)
2. Executors.newCachedThreadPool 創建一個coreSize=0, maxSize=Integer.MAX_VALUE, 每個線程最大空閒時間不能超過60s,否則強制退出(SynchronousQueue)
3. Executors.newSingleThreadExecutor 創建一個coreSize=maxSize=1的線程池,每個線程不限制空閒時間,一直阻塞等待任務,不存在併發,保證任務有序執行完(LinkedBlockingQueue)
4. Executors.newScheduledThreadPool 創建一個coreSize=0, maxSize=Integer.MAX_VALUE,每個線程空閒時間設置0,否則強制退出(DelayedWorkQueue) -
線程池的重要參數
1.allowCoreThreadTimeOut 指定核心線程是否允許超時,非核心線程寫死在代碼裏面一定是有空閒時間限制的boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
2 .keepAliveTime 指定核心線程或者非核心線程的最大空閒時間
3.corePoolSize 指定核心線程數量
4.maximumPoolSize 指定最大線程數量
5.RejectedExecutionHandler 指定使用的拒絕策略(AbortPolicy,DiscardPolicy,DiscardOldestPolicy,CallerRunsPolicy)
6.ThreadFactory 指定創建線程的工廠實現 -
線程池應用----多個任務都完成做統計
//用柵欄 public class Test5 { public static void main(String[] args) throws InterruptedException, ExecutionException { CountDownLatch countDownLatch = new CountDownLatch(5); List<FutureTask> futureTaskList=new ArrayList<>(); for(int i=1;i<=100;i++) { FutureTask<Integer> integerFutureTask = new FutureTask<Integer>(new Task(i,countDownLatch)); futureTaskList.add(integerFutureTask); new Thread(integerFutureTask).start(); } countDownLatch.await(); int count=0; for (FutureTask<Integer> futureTask: futureTaskList ) { count+=futureTask.get(); } System.out.println("統計:"+count); } } class Task implements Callable<Integer> { private Integer integer; private CountDownLatch countDownLatch; public Task(Integer integer) { this.integer = integer; } public Task(Integer integer, CountDownLatch countDownLatch) { this.integer = integer; this.countDownLatch = countDownLatch; } @Override public Integer call() throws Exception { countDownLatch.countDown(); return integer; } }
-
線程池應用—百萬任務如何快速處理
/** * 假設一個任務消耗2毫秒,那麼單線程處理10萬個任務需要200秒 * 使用forkjoin,會將大任務拆成小任務,拆分的每個小任務會有一個線程處理,相當於多個線程同時處理 */ public class ForkJoinTask { public static void main(String[] args) throws ExecutionException, InterruptedException { System.out.println("開始時間:"+new Date()); ForkJoinPool forkJoinPool = new ForkJoinPool(); Long integer = forkJoinPool.submit(new Task(1L, 100000L)).get(); System.out.println("計算結果:"+integer); System.out.println("開始時間:"+new Date()); System.out.println("開始時間2:"+new Date()); Long sum=0L; Long i=1L; while (i<=100000L){ sum+=i; i++; Thread.sleep(2); } System.out.println(sum); System.out.println("開始時間2:"+new Date()); } } class Task extends RecursiveTask<Long>{ private Long start; private Long end; public Task(Long start, Long end) { this.start = start; this.end = end; } @Override protected Long compute() { Long sum=0L; boolean canCompute=(end-start)<=2; if(canCompute){ for(Long i=start;i<=end;i++){ sum+=i; try { Thread.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } } }else { Long middle=(start+end)/2; Task task = new Task(start, middle); Task task1 = new Task(middle + 1, end); task.fork(); task1.fork(); Long join = task.join(); Long join1 = task1.join(); sum=join+join1; } return sum; } } 開始時間:Fri Apr 24 22:28:16 CST 2020 計算結果:5000050000 開始時間:Fri Apr 24 22:28:38 CST 2020 開始時間2:Fri Apr 24 22:28:38 CST 2020 5000050000 開始時間2:Fri Apr 24 22:32:47 CST 2020
-
CountDownLatch和ForkJoinTask對比
1.都可以通過阻塞,等到所有任務執行完再統計結果
2.CountDownLatch沒有任務切分功能,ForkJoinTask可以有任務切分功能
3.CountDownLatch線程開銷大,ForkJoinTask一個線程可以處理一批任務
4.大部分還是使用ForkJoinTask,功能完善
常見問題之線程池
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.