摘要:有三種狀態運行關閉終止。類類,提供了一系列工廠方法用于創建線程池,返回的線程池都實現了接口。線程池的大小一旦達到最大值就會保持不變,在提交新任務,任務將會進入等待隊列中等待。此線程池支持定時以及周期性執行任務的需求。
這是java高并發系列第19篇文章。
本文主要內容介紹Executor框架相關內容
介紹Executor
介紹ExecutorService
介紹線程池ThreadPoolExecutor及案例
介紹定時器ScheduledExecutorService及案例
介紹Excecutors類的使用
介紹Future接口
介紹Callable接口
介紹FutureTask的使用
獲取異步任務的執行結果的幾種方法
Executors框架介紹Executors框架是Doug Lea的神作,通過這個框架,可以很容易的使用線程池高效地處理并行任務。
Excecutor框架主要包含3部分的內容:
任務相關的:包含被執行的任務要實現的接口:Runnable接口或Callable接口
任務的執行相關的:包含任務執行機制的核心接口Executor,以及繼承自Executor的ExecutorService接口。Executor框架中有兩個關鍵的類實現了ExecutorService接口(ThreadPoolExecutor和ScheduleThreadPoolExecutor)
異步計算結果相關的:包含接口Future和實現Future接口的FutureTask類
Executors框架包括:
Executor
ExecutorService
ThreadPoolExecutor
Executors
Future
Callable
FutureTask
CompletableFuture
CompletionService
ExecutorCompletionService
下面我們來一個個介紹其用途和使用方法。
Executor接口Executor接口中定義了方法execute(Runable able)接口,該方法接受一個Runable實例,他來執行一個任務,任務即實現一個Runable接口的類。
ExecutorService接口ExecutorService繼承于Executor接口,他提供了更為豐富的線程實現方法,比如ExecutorService提供關閉自己的方法,以及為跟蹤一個或多個異步任務執行狀況而生成Future的方法。
ExecutorService有三種狀態:運行、關閉、終止。創建后便進入運行狀態,當調用了shutdown()方法時,便進入了關閉狀態,此時意味著ExecutorService不再接受新的任務,但是他還是會執行已經提交的任務,當所有已經提交了的任務執行完后,便達到終止狀態。如果不調用shutdown方法,ExecutorService方法會一直運行下去,系統一般不會主動關閉。
ThreadPoolExecutor類線程池類,實現了ExecutorService接口中所有方法,該類也是我們經常要用到的,非常重要,關于此類有詳細的介紹,可以移步:玩轉java中的線程池
ScheduleThreadPoolExecutor定時器ScheduleThreadPoolExecutor繼承自ScheduleThreadPoolExecutor,他主要用來延遲執行任務,或者定時執行任務。功能和Timer類似,但是ScheduleThreadPoolExecutor更強大、更靈活一些。Timer后臺是單個線程,而ScheduleThreadPoolExecutor可以在創建的時候指定多個線程。
常用方法介紹:
schedule:延遲執行任務1次使用ScheduleThreadPoolExecutor的schedule方法,看一下這個方法的聲明:
public ScheduledFuture> schedule(Runnable command, long delay, TimeUnit unit)
3個參數:command:需要執行的任務
delay:需要延遲的時間
unit:參數2的時間單位,是個枚舉,可以是天、小時、分鐘、秒、毫秒、納秒等
示例代碼:
package com.itsoku.chat18; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; /** * 跟著阿里p7學并發,微信公眾號:javacode2018 */ public class Demo1 { public static void main(String[] args) throws ExecutionException, InterruptedException { System.out.println(System.currentTimeMillis()); ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10); scheduledExecutorService.schedule(() -> { System.out.println(System.currentTimeMillis() + "開始執行"); //模擬任務耗時 try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(System.currentTimeMillis() + "執行結束"); }, 2, TimeUnit.SECONDS); } }
輸出:
1564575180457 1564575185525開始執行 1564575188530執行結束scheduleAtFixedRate:固定的頻率執行任務
使用ScheduleThreadPoolExecutor的scheduleAtFixedRate方法,該方法設置了執行周期,下一次執行時間相當于是上一次的執行時間加上period,任務每次執行完畢之后才會計算下次的執行時間。
看一下這個方法的聲明:
public ScheduledFuture> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit);
4個參數:command:表示要執行的任務
initialDelay:表示延遲多久執行第一次
period:連續執行之間的時間間隔
unit:參數2和參數3的時間單位,是個枚舉,可以是天、小時、分鐘、秒、毫秒、納秒等
假設系統調用scheduleAtFixedRate的時間是T1,那么執行時間如下:
第1次:T1+initialDelay
第2次:T1+initialDelay+period
第3次:T1+initialDelay+2*period
第n次:T1+initialDelay+(n-1)*period
示例代碼:
package com.itsoku.chat18; import java.sql.Time; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; /** * 跟著阿里p7學并發,微信公眾號:javacode2018 */ public class Demo2 { public static void main(String[] args) throws ExecutionException, InterruptedException { System.out.println(System.currentTimeMillis()); //任務執行計數器 AtomicInteger count = new AtomicInteger(1); ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10); scheduledExecutorService.scheduleAtFixedRate(() -> { int currCount = count.getAndIncrement(); System.out.println(Thread.currentThread().getName()); System.out.println(System.currentTimeMillis() + "第" + currCount + "次" + "開始執行"); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(System.currentTimeMillis() + "第" + currCount + "次" + "執行結束"); }, 1, 1, TimeUnit.SECONDS); } }
前面6次輸出結果:
1564576404181 pool-1-thread-1 1564576405247第1次開始執行 1564576407251第1次執行結束 pool-1-thread-1 1564576407251第2次開始執行 1564576409252第2次執行結束 pool-1-thread-2 1564576409252第3次開始執行 1564576411255第3次執行結束 pool-1-thread-1 1564576411256第4次開始執行 1564576413260第4次執行結束 pool-1-thread-3 1564576413260第5次開始執行 1564576415265第5次執行結束 pool-1-thread-2 1564576415266第6次開始執行 1564576417269第6次執行結束
代碼中設置的任務第一次執行時間是系統啟動之后延遲一秒執行。后面每次時間間隔1秒,從輸出中可以看出系統啟動之后過了1秒任務第一次執行(1、3行輸出),輸出的結果中可以看到任務第一次執行結束時間和第二次的結束時間一樣,為什么會這樣?前面有介紹,任務當前執行完畢之后會計算下次執行時間,下次執行時間為上次執行的開始時間+period,第一次開始執行時間是1564576405247,加1秒為1564576406247,這個時間小于第一次結束的時間了,說明小于系統當前時間了,會立即執行。
scheduleWithFixedDelay:固定的間隔執行任務使用ScheduleThreadPoolExecutor的scheduleWithFixedDelay方法,該方法設置了執行周期,與scheduleAtFixedRate方法不同的是,下一次執行時間是上一次任務執行完的系統時間加上period,因而具體執行時間不是固定的,但周期是固定的,是采用相對固定的延遲來執行任務。看一下這個方法的聲明:
public ScheduledFuture> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit);
4個參數:command:表示要執行的任務
initialDelay:表示延遲多久執行第一次
period:表示下次執行時間和上次執行結束時間之間的間隔時間
unit:參數2和參數3的時間單位,是個枚舉,可以是天、小時、分鐘、秒、毫秒、納秒等
假設系統調用scheduleAtFixedRate的時間是T1,那么執行時間如下:
第1次:T1+initialDelay,執行結束時間:E1
第2次:E1+period,執行結束時間:E2
第3次:E2+period,執行結束時間:E3
第4次:E3+period,執行結束時間:E4
第n次:上次執行結束時間+period
示例代碼:
package com.itsoku.chat18; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; /** * 跟著阿里p7學并發,微信公眾號:javacode2018 */ public class Demo3 { public static void main(String[] args) throws ExecutionException, InterruptedException { System.out.println(System.currentTimeMillis()); //任務執行計數器 AtomicInteger count = new AtomicInteger(1); ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10); scheduledExecutorService.scheduleWithFixedDelay(() -> { int currCount = count.getAndIncrement(); System.out.println(Thread.currentThread().getName()); System.out.println(System.currentTimeMillis() + "第" + currCount + "次" + "開始執行"); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(System.currentTimeMillis() + "第" + currCount + "次" + "執行結束"); }, 1, 3, TimeUnit.SECONDS); } }
前幾次輸出如下:
1564578510983 pool-1-thread-1 1564578512087第1次開始執行 1564578514091第1次執行結束 pool-1-thread-1 1564578517096第2次開始執行 1564578519100第2次執行結束 pool-1-thread-2 1564578522103第3次開始執行 1564578524105第3次執行結束 pool-1-thread-1 1564578527106第4次開始執行 1564578529106第4次執行結束
延遲1秒之后執行第1次,后面每次的執行時間和上次執行結束時間間隔3秒。
scheduleAtFixedRate和scheduleWithFixedDelay示例建議多看2遍。
定時任務有異常會怎么樣?示例代碼:
package com.itsoku.chat18; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; /** * 跟著阿里p7學并發,微信公眾號:javacode2018 */ public class Demo4 { public static void main(String[] args) throws ExecutionException, InterruptedException { System.out.println(System.currentTimeMillis()); //任務執行計數器 AtomicInteger count = new AtomicInteger(1); ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10); ScheduledFuture> scheduledFuture = scheduledExecutorService.scheduleWithFixedDelay(() -> { int currCount = count.getAndIncrement(); System.out.println(Thread.currentThread().getName()); System.out.println(System.currentTimeMillis() + "第" + currCount + "次" + "開始執行"); System.out.println(10 / 0); System.out.println(System.currentTimeMillis() + "第" + currCount + "次" + "執行結束"); }, 1, 1, TimeUnit.SECONDS); TimeUnit.SECONDS.sleep(5); System.out.println(scheduledFuture.isCancelled()); System.out.println(scheduledFuture.isDone()); } }
系統輸出如下內容就再也沒有輸出了:
1564578848143 pool-1-thread-1 1564578849226第1次開始執行 false true
先說補充點知識:schedule、scheduleAtFixedRate、scheduleWithFixedDelay這幾個方法有個返回值ScheduledFuture,通過ScheduledFuture可以對執行的任務做一些操作,如判斷任務是否被取消、是否執行完成。
再回到上面代碼,任務中有個10/0的操作,會觸發異常,發生異常之后沒有任何現象,被ScheduledExecutorService內部給吞掉了,然后這個任務再也不會執行了,scheduledFuture.isDone()輸出true,表示這個任務已經結束了,再也不會被執行了。所以如果程序有異常,開發者自己注意處理一下,不然跑著跑著發現任務怎么不跑了,也沒有異常輸出。
取消定時任務的執行可能任務執行一會,想取消執行,可以調用ScheduledFuture的cancel方法,參數表示是否給任務發送中斷信號。
package com.itsoku.chat18; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; /** * 跟著阿里p7學并發,微信公眾號:javacode2018 */ public class Demo5 { public static void main(String[] args) throws ExecutionException, InterruptedException { System.out.println(System.currentTimeMillis()); //任務執行計數器 AtomicInteger count = new AtomicInteger(1); ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1); ScheduledFuture> scheduledFuture = scheduledExecutorService.scheduleWithFixedDelay(() -> { int currCount = count.getAndIncrement(); System.out.println(Thread.currentThread().getName()); System.out.println(System.currentTimeMillis() + "第" + currCount + "次" + "開始執行"); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(System.currentTimeMillis() + "第" + currCount + "次" + "執行結束"); }, 1, 1, TimeUnit.SECONDS); TimeUnit.SECONDS.sleep(5); scheduledFuture.cancel(false); TimeUnit.SECONDS.sleep(1); System.out.println("任務是否被取消:"+scheduledFuture.isCancelled()); System.out.println("任務是否已完成:"+scheduledFuture.isDone()); } }
輸出:
1564579843190 pool-1-thread-1 1564579844255第1次開始執行 1564579846260第1次執行結束 pool-1-thread-1 1564579847263第2次開始執行 任務是否被取消:true 任務是否已完成:true 1564579849267第2次執行結束
輸出中可以看到任務被取消成功了。
Executors類Executors類,提供了一系列工廠方法用于創建線程池,返回的線程池都實現了ExecutorService接口。常用的方法有:
newSingleThreadExecutor
public static ExecutorService newSingleThreadExecutor() public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory)
創建一個單線程的線程池。這個線程池只有一個線程在工作,也就是相當于單線程串行執行所有任務。如果這個唯一的線程因為異常結束,那么會有一個新的線程來替代它。此線程池保證所有任務的執行順序按照任務的提交順序執行。內部使用了無限容量的LinkedBlockingQueue阻塞隊列來緩存任務,任務如果比較多,單線程如果處理不過來,會導致隊列堆滿,引發OOM。
newFixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads) public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory)
創建固定大小的線程池。每次提交一個任務就創建一個線程,直到線程達到線程池的最大大小。線程池的大小一旦達到最大值就會保持不變,在提交新任務,任務將會進入等待隊列中等待。如果某個線程因為執行異常而結束,那么線程池會補充一個新線程。內部使用了無限容量的LinkedBlockingQueue阻塞隊列來緩存任務,任務如果比較多,如果處理不過來,會導致隊列堆滿,引發OOM。
newCachedThreadPool
public static ExecutorService newCachedThreadPool() public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory)
創建一個可緩存的線程池。如果線程池的大小超過了處理任務所需要的線程,那么就會回收部分空閑(60秒處于等待任務到來)的線程,當任務數增加時,此線程池又可以智能的添加新線程來處理任務。此線程池的最大值是Integer的最大值(2^31-1)。內部使用了SynchronousQueue同步隊列來緩存任務,此隊列的特性是放入任務時必須要有對應的線程獲取任務,任務才可以放入成功。如果處理的任務比較耗時,任務來的速度也比較快,會創建太多的線程引發OOM。
newScheduledThreadPool
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory)
創建一個大小無限的線程池。此線程池支持定時以及周期性執行任務的需求。
在《阿里巴巴java開發手冊》中指出了線程資源必須通過線程池提供,不允許在應用中自行顯示的創建線程,這樣一方面是線程的創建更加規范,可以合理控制開辟線程的數量;另一方面線程的細節管理交給線程池處理,優化了資源的開銷。而線程池不允許使用Executors去創建,而要通過ThreadPoolExecutor方式,這一方面是由于jdk中Executor框架雖然提供了如newFixedThreadPool()、newSingleThreadExecutor()、newCachedThreadPool()等創建線程池的方法,但都有其局限性,不夠靈活;另外由于前面幾種方法內部也是通過ThreadPoolExecutor方式實現,使用ThreadPoolExecutor有助于大家明確線程池的運行規則,創建符合自己的業務場景需要的線程池,避免資源耗盡的風險。
Future、Callable接口Future接口定義了操作異步異步任務執行一些方法,如獲取異步任務的執行結果、取消任務的執行、判斷任務是否被取消、判斷任務執行是否完畢等。
Callable接口中定義了需要有返回的任務需要實現的方法。
@FunctionalInterface public interface Callable{ V call() throws Exception; }
比如主線程讓一個子線程去執行任務,子線程可能比較耗時,啟動子線程開始執行任務后,主線程就去做其他事情了,過了一會才去獲取子任務的執行結果。
獲取異步任務執行結果示例代碼:
package com.itsoku.chat18; import java.util.concurrent.*; /** * 跟著阿里p7學并發,微信公眾號:javacode2018 */ public class Demo6 { public static void main(String[] args) throws ExecutionException, InterruptedException { ExecutorService executorService = Executors.newFixedThreadPool(1); Futureresult = executorService.submit(() -> { System.out.println(System.currentTimeMillis() + "," + Thread.currentThread().getName()+",start!"); TimeUnit.SECONDS.sleep(5); System.out.println(System.currentTimeMillis() + "," + Thread.currentThread().getName()+",end!"); return 10; }); System.out.println(System.currentTimeMillis() + "," + Thread.currentThread().getName()); System.out.println(System.currentTimeMillis() + "," + Thread.currentThread().getName() + ",結果:" + result.get()); } }
輸出:
1564581941442,main 1564581941442,pool-1-thread-1,start! 1564581946447,pool-1-thread-1,end! 1564581941442,main,結果:10
代碼中創建了一個線程池,調用線程池的submit方法執行任務,submit參數為Callable接口:表示需要執行的任務有返回值,submit方法返回一個Future對象,Future相當于一個憑證,可以在任意時間拿著這個憑證去獲取對應任務的執行結果(調用其get方法),代碼中調用了result.get()方法之后,此方法會阻塞當前線程直到任務執行結束。
超時獲取異步任務執行結果可能任務執行比較耗時,比如耗時1分鐘,我最多只能等待10秒,如果10秒還沒返回,我就去做其他事情了。
剛好get有個超時的方法,聲明如下:
V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
示例代碼:
package com.itsoku.chat18; import java.util.concurrent.*; /** * 跟著阿里p7學并發,微信公眾號:javacode2018 */ public class Demo8 { public static void main(String[] args) throws ExecutionException, InterruptedException { ExecutorService executorService = Executors.newFixedThreadPool(1); Futureresult = executorService.submit(() -> { System.out.println(System.currentTimeMillis() + "," + Thread.currentThread().getName()+",start!"); TimeUnit.SECONDS.sleep(5); System.out.println(System.currentTimeMillis() + "," + Thread.currentThread().getName()+",end!"); return 10; }); System.out.println(System.currentTimeMillis() + "," + Thread.currentThread().getName()); try { System.out.println(System.currentTimeMillis() + "," + Thread.currentThread().getName() + ",結果:" + result.get(3,TimeUnit.SECONDS)); } catch (TimeoutException e) { e.printStackTrace(); } executorService.shutdown(); } }
輸出:
1564583177139,main 1564583177139,pool-1-thread-1,start! java.util.concurrent.TimeoutException at java.util.concurrent.FutureTask.get(FutureTask.java:205) at com.itsoku.chat18.Demo8.main(Demo8.java:19) 1564583182142,pool-1-thread-1,end!
任務執行中休眠了5秒,get方法獲取執行結果,超時時間是3秒,3秒還未獲取到結果,get觸發了TimeoutException異常,當前線程從阻塞狀態蘇醒了。
Future其他方法介紹一下
cancel:取消在執行的任務,參數表示是否對執行的任務發送中斷信號,方法聲明如下:
boolean cancel(boolean mayInterruptIfRunning);
isCancelled:用來判斷任務是否被取消
isDone:判斷任務是否執行完畢。
cancel方法來個示例:
package com.itsoku.chat18; import java.util.concurrent.*; /** * 跟著阿里p7學并發,微信公眾號:javacode2018 */ public class Demo7 { public static void main(String[] args) throws ExecutionException, InterruptedException { ExecutorService executorService = Executors.newFixedThreadPool(1); Futureresult = executorService.submit(() -> { System.out.println(System.currentTimeMillis() + "," + Thread.currentThread().getName()+",start!"); TimeUnit.SECONDS.sleep(5); System.out.println(System.currentTimeMillis() + "," + Thread.currentThread().getName()+",end!"); return 10; }); executorService.shutdown(); TimeUnit.SECONDS.sleep(1); result.cancel(false); System.out.println(result.isCancelled()); System.out.println(result.isDone()); TimeUnit.SECONDS.sleep(5); System.out.println(System.currentTimeMillis() + "," + Thread.currentThread().getName()); System.out.println(System.currentTimeMillis() + "," + Thread.currentThread().getName() + ",結果:" + result.get()); executorService.shutdown(); } }
輸出:
1564583031646,pool-1-thread-1,start! true true 1564583036649,pool-1-thread-1,end! 1564583037653,main Exception in thread "main" java.util.concurrent.CancellationException at java.util.concurrent.FutureTask.report(FutureTask.java:121) at java.util.concurrent.FutureTask.get(FutureTask.java:192) at com.itsoku.chat18.Demo7.main(Demo7.java:24)
輸出2個true,表示任務已被取消,已完成,最后調用get方法會觸發CancellationException異常。
總結:從上面可以看出Future、Callable接口需要結合ExecutorService來使用,需要有線程池的支持。
FutureTask類FutureTask除了實現Future接口,還實現了Runnable接口,因此FutureTask可以交給Executor執行,也可以交給線程執行執行(Thread有個Runnable的構造方法),FutureTask表示帶返回值結果的任務。
上面我們演示的是通過線程池執行任務然后獲取執行結果。
這次我們通過FutureTask類,自己啟動一個線程來獲取執行結果,示例如下:
package com.itsoku.chat18; import java.util.concurrent.*; /** * 跟著阿里p7學并發,微信公眾號:javacode2018 */ public class Demo9 { public static void main(String[] args) throws ExecutionException, InterruptedException { FutureTaskfutureTask = new FutureTask (()->{ System.out.println(System.currentTimeMillis() + "," + Thread.currentThread().getName()+",start!"); TimeUnit.SECONDS.sleep(5); System.out.println(System.currentTimeMillis() + "," + Thread.currentThread().getName()+",end!"); return 10; }); System.out.println(System.currentTimeMillis()+","+Thread.currentThread().getName()); new Thread(futureTask).start(); System.out.println(System.currentTimeMillis()+","+Thread.currentThread().getName()); System.out.println(System.currentTimeMillis()+","+Thread.currentThread().getName()+",結果:"+futureTask.get()); } }
輸出:
1564585122547,main 1564585122547,main 1564585122547,Thread-0,start! 1564585127549,Thread-0,end! 1564585122547,main,結果:10
大家可以回過頭去看一下上面用線程池的submit方法返回的Future實際類型正是FutureTask對象,有興趣的可以設置個斷點去看看。
FutureTask類還是相當重要的,標記一下。
下面3個類,下一篇文章進行詳解介紹CompletableFuture
介紹CompletionService
介紹ExecutorCompletionService
java高并發系列java高并發系列 - 第1天:必須知道的幾個概念
java高并發系列 - 第2天:并發級別
java高并發系列 - 第3天:有關并行的兩個重要定律
java高并發系列 - 第4天:JMM相關的一些概念
java高并發系列 - 第5天:深入理解進程和線程
java高并發系列 - 第6天:線程的基本操作
java高并發系列 - 第7天:volatile與Java內存模型
java高并發系列 - 第8天:線程組
java高并發系列 - 第9天:用戶線程和守護線程
java高并發系列 - 第10天:線程安全和synchronized關鍵字
java高并發系列 - 第11天:線程中斷的幾種方式
java高并發系列 - 第12天JUC:ReentrantLock重入鎖
java高并發系列 - 第13天:JUC中的Condition對象
java高并發系列 - 第14天:JUC中的LockSupport工具類,必備技能
java高并發系列 - 第15天:JUC中的Semaphore(信號量)
java高并發系列 - 第16天:JUC中等待多線程完成的工具類CountDownLatch,必備技能
java高并發系列 - 第17天:JUC中的循環柵欄CyclicBarrier的6種使用場景
java高并發系列 - 第18天:JAVA線程池,這一篇就夠了
java高并發系列 - 第19天:JUC中的Executor框架詳解1
高并發系列連載中,感興趣的加我微信itsoku,一起交流,關注公眾號:路人甲Java,每天獲取最新連載文章!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/75737.html
摘要:方法由兩個參數,表示期望的值,表示要給設置的新值。操作包含三個操作數內存位置預期原值和新值。如果處的值尚未同時更改,則操作成功。中就使用了這樣的操作。上面操作還有一點是將事務范圍縮小了,也提升了系統并發處理的性能。 這是java高并發系列第21篇文章。 本文主要內容 從網站計數器實現中一步步引出CAS操作 介紹java中的CAS及CAS可能存在的問題 悲觀鎖和樂觀鎖的一些介紹及數據庫...
摘要:示例執行一批任務,然后消費執行結果代碼如下跟著阿里學并發,微信公眾號輸出代碼中傳入了一批任務進行處理,最終將所有處理完成的按任務完成的先后順序傳遞給進行消費了。 這是java高并發系列第20篇文章。 本文內容 ExecutorCompletionService出現的背景 介紹CompletionService接口及常用的方法 介紹ExecutorCompletionService類及...
摘要:如問到是否使用某框架,實際是是問該框架的使用場景,有什么特點,和同類可框架對比一系列的問題。這兩個方向的區分點在于工作方向的側重點不同。 [TOC] 這是一份來自嗶哩嗶哩的Java面試Java面試 32個核心必考點完全解析(完) 課程預習 1.1 課程內容分為三個模塊 基礎模塊: 技術崗位與面試 計算機基礎 JVM原理 多線程 設計模式 數據結構與算法 應用模塊: 常用工具集 ...
摘要:我的是忙碌的一年,從年初備戰實習春招,年三十都在死磕源碼,三月份經歷了阿里五次面試,四月順利收到實習。因為我心理很清楚,我的目標是阿里。所以在收到阿里之后的那晚,我重新規劃了接下來的學習計劃,將我的短期目標更新成拿下阿里轉正。 我的2017是忙碌的一年,從年初備戰實習春招,年三十都在死磕JDK源碼,三月份經歷了阿里五次面試,四月順利收到實習offer。然后五月懷著忐忑的心情開始了螞蟻金...
摘要:從使用到原理學習線程池關于線程池的使用,及原理分析分析角度新穎面向切面編程的基本用法基于注解的實現在軟件開發中,分散于應用中多出的功能被稱為橫切關注點如事務安全緩存等。 Java 程序媛手把手教你設計模式中的撩妹神技 -- 上篇 遇一人白首,擇一城終老,是多么美好的人生境界,她和他歷經風雨慢慢變老,回首走過的點點滴滴,依然清楚的記得當初愛情萌芽的模樣…… Java 進階面試問題列表 -...
閱讀 2901·2021-11-23 09:51
閱讀 1547·2021-11-15 11:36
閱讀 3006·2021-10-13 09:40
閱讀 1863·2021-09-28 09:35
閱讀 13040·2021-09-22 15:00
閱讀 1367·2019-08-29 13:56
閱讀 2924·2019-08-29 13:04
閱讀 2698·2019-08-28 18:06