<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
1:快取執行緒池(不推薦)
2:固定容量執行緒池(不推薦)
3:單個執行緒池(不推薦)
4:定時任務執行緒池(不推薦)
5:通過ThreadPoolExecutor構造方法建立執行緒池(阿里巴巴開發手冊十分推薦)
前面4種建立執行緒池的方式都是通過Executors的靜態方法來建立。
ExecutorService executorService = Executors.newCachedThreadPool(); for (int i = 0; i < 10; i++) { final int finalI = i; executorService.execute(new Runnable() { public void run() { System.out.println(Thread.currentThread().getName()+"<thread->run>"+ finalI); } }); }
為什麼不推薦使用快取執行緒池?
原始碼分析
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, 2147483647, 60L, TimeUnit.SECONDS, new SynchronousQueue()); }
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); }
通過上面兩個程式碼片段,我們可以看出CachedThreadPool的maximumPoolSize為Integer的最大值2147483647,相當於可以無限的建立執行緒,而建立執行緒是需要記憶體的,這樣就會造成記憶體溢位,而且一般的機器也沒用那麼大的記憶體給它建立這麼大量的執行緒。
newFixedThreadPool(int num),num就是我們要指定的固定執行緒數量
ExecutorService executorService = Executors.newFixedThreadPool(5); for (int i = 0; i < 10; i++) { final int finalI = i; executorService.execute(new Runnable() { public void run() { System.out.println(Thread.currentThread().getName()+"<thread->run>"+ finalI); } }); }
輸出:
pool-1-thread-5<thread->run>4
pool-1-thread-4<thread->run>3
pool-1-thread-5<thread->run>5
pool-1-thread-3<thread->run>2
pool-1-thread-3<thread->run>8
pool-1-thread-3<thread->run>9
pool-1-thread-2<thread->run>1
pool-1-thread-1<thread->run>0
pool-1-thread-5<thread->run>7
pool-1-thread-4<thread->run>6
可以看出起到了執行緒的複用。
為什麼FixedThreadPool是固定執行緒池?
原始碼分析
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()); }
通過這個原始碼可以看出,核心執行緒數(corePoolSize)和最大執行緒數(maximumPoolSize)都為nThreads,因為只有這樣,執行緒池才不會進行擴容,執行緒數才固定。
ExecutorService executorService = Executors.newSingleThreadExecutor(); for (int i = 0; i < 10; i++) { final int finalI = i; executorService.execute(new Runnable() { public void run() { System.out.println(Thread.currentThread().getName()+"<thread->run>"+ finalI); } }); }
為什麼SingleThreadExecutor只含有一個執行緒?
原始碼分析
public static ExecutorService newSingleThreadExecutor() { return new Executors.FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue())); }
通過這個原始碼可以看出,核心執行緒數(corePoolSize)和最大執行緒數(maximumPoolSize)都為1,所以它只含有一個執行緒。
int initDelay=10; //初始化延時 int period=1;//初始化延遲過了之後,每秒的延時 ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10); scheduledExecutorService.scheduleAtFixedRate(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+"<thread->run>"); } },initDelay,period, TimeUnit.SECONDS);
這段程式碼的效果是:程式執行之後等10秒,然後輸出第一次結果,之後每隔1秒輸出一次結果。
為什麼不推薦使用ScheduledThreadPool?
原始碼分析
public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, 2147483647, 10L, TimeUnit.MILLISECONDS, new ScheduledThreadPoolExecutor.DelayedWorkQueue()); }
可以看出ScheduledThreadPool的最大執行緒數(maximumPoolSize)為Integer的最大值2147483647,相當於可以無限的建立執行緒,而建立執行緒是需要記憶體的,這樣就會造成記憶體溢位,而且一般的機器也沒用那麼大的記憶體給它建立這麼大量的執行緒。
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 20, 2L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy()); for (int i = 0; i < 12; i++) { final int finalI = i; threadPoolExecutor.execute(new Runnable() { public void run() { System.out.println(Thread.currentThread().getName()+"<thread->run>"+ finalI); } }); }
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { }
ArrayBlockingQueue:有界阻塞佇列。佇列有大小限制,當容量超過時則會觸發擴容或者拒絕策略。
public ArrayBlockingQueue(int capacity) { this(capacity, false); }
LinkedBlockingQueue:無界阻塞佇列,佇列無大小限制,可能會造成記憶體溢位。
public LinkedBlockingQueue() { this(2147483647); }
AbortPolicy:直接拋異常
public static class AbortPolicy implements RejectedExecutionHandler { public AbortPolicy() { } public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { throw new RejectedExecutionException("Task " + r.toString() + " rejected from " + e.toString()); } }
DiscardPolicy:不作任何操作。默默丟棄任務
public static class DiscardPolicy implements RejectedExecutionHandler { public DiscardPolicy() { } public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { } }
DiscardOldestPolicy:丟掉存在時間最長的任務
public static class DiscardOldestPolicy implements RejectedExecutionHandler { public DiscardOldestPolicy() { } public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { if (!e.isShutdown()) { e.getQueue().poll(); e.execute(r); } } }
CallerRunsPolicy:讓提交任務的執行緒去處理任務
public static class CallerRunsPolicy implements RejectedExecutionHandler { public CallerRunsPolicy() { } public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { if (!e.isShutdown()) { r.run(); } } }
threadFactory
ThreadFactory threadFactory = Executors.defaultThreadFactory(); threadFactory.newThread(new Runnable() { @Override public void run() { System.out.println("threadFactory"); } }).start();
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 20, 2L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy()); for (int i = 0; i < 26; i++) { //並行數26 final int finalI = i; threadPoolExecutor.execute(new Runnable() { public void run() { System.out.println(Thread.currentThread().getName()+"<thread->run>"+ finalI); } }); } /** * 核心執行緒數=10,最大執行緒數=20,故可擴容執行緒數=20-10 * BlockingQueue的大小為5,故等待區的大小為5,也就是當並行數<=核心執行緒數+5不會擴容,並行數大於16才會擴容 * * 觸發擴容:並行數>核心執行緒數+阻塞佇列的大小 * 對於這段程式碼,如果來了26個並行,10個並行會被核心執行緒處理,5個會在等待區,剩下11個會因為等待區滿了而觸發擴容 * 因為這裡最多能夠擴容10個,這裡卻是11個,所以會觸發拒絕策略 */
對於這段程式碼,如果來了26個並行,10個並行會被核心執行緒處理,5個會在等待區,剩下11個會因為等待區滿了而觸發擴容,但是又因為因為這裡最多能夠擴容10個,這裡卻是11個,所以會觸發拒絕策略。
觸發擴容:並行數>核心執行緒數(corePoolSize)+阻塞佇列(workQueue)的大小
下期文章連結https://www.jb51.net/article/241589.htm
到此這篇關於非常適合新手學生的Java執行緒池超詳細分析的文章就介紹到這了,更多相關Java 執行緒池內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45