Java四種執行緒池使用方法
阿新 • • 發佈:2019-01-26
1.new Thread的弊端
執行一個非同步任務你還只是如下new Thread嗎?1234567 | new Thread( new Runnable() { @Override public void run() { // TODO Auto-generated method stub } }).start(); |
1-1 說說弊端:
a. 每次new Thread新建物件效能差。
b. 執行緒缺乏統一管理,可能無限制新建執行緒,相互之間競爭,及可能佔用過多系統資源導致宕機或oom。
c. 缺乏更多功能,如定時執行、定期執行、執行緒中斷。
1-2 相比new Thread,Java提供的四種執行緒池的好處在於:
a. 重用存在的執行緒,減少物件建立、消亡的開銷,效能佳。b. 可有效控制最大併發執行緒數,提高系統資源的使用率,同時避免過多資源競爭,避免堵塞。
c. 提供定時執行、定期執行、單執行緒、併發數控制等功能。
2.Executors提供四種執行緒池
newCachedThreadPool建立一個可快取執行緒池,如果執行緒池長度超過處理需要,可靈活回收空閒執行緒,若無可回收,則新建執行緒。執行緒池的規模不存在限制。
newFixedThreadPool 建立一個固定長度執行緒池,可控制執行緒最大併發數,超出的執行緒會在佇列中等待。
newScheduledThreadPool 建立一個固定長度執行緒池,支援定時及週期性任務執行。
newSingleThreadExecutor 建立一個單執行緒化的執行緒池,它只會用唯一的工作執行緒來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先順序)執行。
將執行緒放入執行緒池的兩種方法
2- Executor 介面中的
3.例項
3-1 newCachedThreadPool
package com.th.threadPool; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * Created by Administrator on 2018/6/6. * newCachedThreadPool建立一個可快取執行緒池,如果執行緒池長度超過處理需要,可靈活回收空閒執行緒, * 若無可回收,則新建執行緒。執行緒池的規模不存在限制。*/ public class NewCachedThreadPool { public static void main(String[] args) { ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); for (int i = 0; i < 10; i++) { final int index = i; try { Thread.sleep(index * 1000); } catch (InterruptedException e) { e.printStackTrace(); } //1- 在未來某個時間執行給定的命令。 // 該命令可能在新的執行緒、已入池的執行緒或者正呼叫的執行緒中執行,這由 Executor 實現決定。 cachedThreadPool.execute(new Runnable() { @Override public void run() { System.out.println(index); } }); //2- 提交一個 Runnable 任務用於執行,並返回一個表示該任務的 Future。 // 該 Future 的 get 方法在成功完成時將會返回給定的結果 cachedThreadPool.submit(new Runnable() { @Override public void run() { System.out.println(index); } }); } cachedThreadPool.shutdown(); } }
3-2 newFixedThreadPool
package com.th.threadPool; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * Created by Administrator on 2018/6/6. * * newFixedThreadPool 建立一個固定長度執行緒池,可控制執行緒最大併發數,超出的執行緒會在佇列中等待。 */ public class NewFixedThreadPool { public static void main(String[] args) { ExecutorService fixedThreadPool = Executors.newFixedThreadPool(2); for (int i = 0; i < 10; i++) { final int index = i; //1- 在未來某個時間執行給定的命令。 // 該命令可能在新的執行緒、已入池的執行緒或者正呼叫的執行緒中執行,這由 Executor 實現決定。 fixedThreadPool.execute(new Runnable() { @Override public void run() { threadRunMethod(index); } }); //2- 提交一個 Runnable 任務用於執行,並返回一個表示該任務的 Future。 // 該 Future 的 get 方法在成功完成時將會返回給定的結果 fixedThreadPool.submit(new Runnable() { @Override public void run() { threadRunMethod(index); } }); } fixedThreadPool.shutdown(); } /** * * @param index */ private static void threadRunMethod(int index) { try { System.out.println(index); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } }
3-3 newScheduledThreadPool
package com.th.threadPool; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; /** * Created by Administrator on 2018/6/6. * newScheduledThreadPool 建立一個固定長度執行緒池,支援定時及週期性任務執行。 */ public class NewScheduledThreadPool { public static void main(String[] args) { ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5); //testSchedule(scheduledExecutorService); //testScheduleAtFixedRate(scheduledExecutorService); testScheduleWithFixedDelay(scheduledExecutorService); // 終止執行緒池 //scheduledExecutorService.shutdown(); } /** * * 跟 testScheduleAtFixedRate 非常類似,就是延遲的時間有點區別 * 建立並執行一個在給定初始延遲後首次啟用的定期操作,後續操作具有給定的週期; * 也就是將在 initialDelay 後開始執行,然後在 initialDelay+period 後執行, * 接著在 initialDelay + 2 * period 後執行,依此類推。 * * 如果任務裡面執行的時間大於 period 的時間,下一次的任務會推遲執行。 * 推遲的時間 : 等到上次的任務執行完之後再延遲period 的時間後執行。 * @param scheduledExecutorService */ private static void testScheduleWithFixedDelay(ScheduledExecutorService scheduledExecutorService) { scheduledExecutorService.scheduleWithFixedDelay(new Runnable() { @Override public void run() { try { System.out.println("延遲2秒,再3秒執行一次"); //如果任務裡面執行的時間大於 period 的時間,下一次的任務會推遲執行。 //本次任務執行完後下次的任務還需要延遲period時間後再執行 Thread.sleep(6*1000); } catch (InterruptedException e) { e.printStackTrace(); } } },2,3,TimeUnit.SECONDS); } /** * 建立並執行一個在給定初始延遲後首次啟用的定期操作,後續操作具有給定的週期; * 也就是將在 initialDelay 後開始執行,然後在 initialDelay+period 後執行, * 接著在 initialDelay + 2 * period 後執行,依此類推。 * * 如果任務裡面執行的時間大於 period 的時間,下一次的任務會推遲執行。 * 推遲的時間 : 等到上次的任務執行完就立馬執行。 * @param scheduledExecutorService */ private static void testScheduleAtFixedRate(ScheduledExecutorService scheduledExecutorService) { scheduledExecutorService.scheduleAtFixedRate(new Runnable() { @Override public void run() { try { System.out.println("延遲2秒,再3秒執行一次"); //如果任務裡面執行的時間大於 period 的時間,下一次的任務會推遲執行。 //如果任務裡面執行的時間大於 period 的時間,本次任務執行完後,下次任務立馬執行。 Thread.sleep(6*1000); } catch (InterruptedException e) { e.printStackTrace(); } } },2,3,TimeUnit.SECONDS); } /** * 建立並執行在給定延遲後啟用的一次性操作 * @param scheduledExecutorService */ private static void testSchedule(ScheduledExecutorService scheduledExecutorService) { scheduledExecutorService.schedule(new Runnable() { @Override public void run() { System.out.println("delay 3 seconds"); } }, 3, TimeUnit.SECONDS); } }
3-4 newSingleThreadExecutor
package com.th.threadPool; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * Created by Administrator on 2018/6/6. * newSingleThreadExecutor 建立一個單執行緒化的執行緒池,它只會用唯一的工作執行緒來執行任務, * 保證所有任務按照指定順序(FIFO, LIFO, 優先順序)執行。 */ public class NewSingleThreadExecutor { public static void main(String[] args) { ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); for (int i = 0; i < 10; i++) { final int index = i; /*singleThreadExecutor.execute(new Runnable() { @Override public void run() { try { System.out.println("newSingleThreadExecutor: " + index); Thread.sleep(2*1000); } catch (Exception e) { e.printStackTrace(); } } });*/ singleThreadExecutor.submit(new Runnable() { @Override public void run() { try { System.out.println("newSingleThreadExecutor: " + index); Thread.sleep(2*1000); } catch (Exception e) { e.printStackTrace(); } } }); } singleThreadExecutor.shutdown(); } }