池化技術:減小每次獲取資源的消耗,提升對資源的利用率。
線程池提供了一種限制和管理資源(包括執行一個任務)。 每一個線程池還維護一些基本統計信息,例如已完成任務的數量。編程
使用線程池的好處:數組
public void execute(Runnable command) { // 若是任務爲null,則拋出異常。 if (command == null) throw new NullPointerException(); // ctl 中保存的線程池當前的一些狀態信息 AtomicInteger int c = ctl.get(); //判斷當前線程池中執行的任務數量是否小於corePoolSize if (workerCountOf(c) < corePoolSize) { //若是小於,則經過addWorker新建一個線程,而後,啓動該線程從而執行任務。 if (addWorker(command, true)) return; c = ctl.get(); } //經過 isRunning 方法判斷線程池狀態 //線程池處於 RUNNING 狀態纔會被而且隊列能夠加入任務 if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); // 再次獲取線程池狀態,若是線程池狀態不是 RUNNING 狀態就須要從任務隊列中移除任務。 // 並嘗試判斷線程是否所有執行完畢。同時執行拒絕策略。 if (! isRunning(recheck) && remove(command)) reject(command); // 若是當前線程池爲空就新建立一個線程並執行。 else if (workerCountOf(recheck) == 0) addWorker(null, false); } //經過addWorker新建一個線程,並將任務(command)添加到該線程中; //而後,啓動該線程從而執行任務。 //若是addWorker執行失敗,則經過reject()執行相應的拒絕策略的內容。 else if (!addWorker(command, false)) reject(command); }
線程池建立線程的時候,會將線程封裝成工做線程Worker,Worker在執行完成任務以後,還會循環獲取工做隊列利的任務來執行。
final void runWorker(Worker w) { Thread wt = Thread.currentThread(); Runnable task = w.firstTask; w.firstTask = null; w.unlock(); // allow interrupts boolean completedAbruptly = true; try { while (task != null || (task = getTask()) != null) {//循環執行任務 w.lock(); //若是線程池正在中止,確保線程被中斷 if ((runStateAtLeast(ctl.get(), STOP) || (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) && !wt.isInterrupted()) wt.interrupt(); try { beforeExecute(wt, task); Throwable thrown = null; try { task.run(); } catch (RuntimeException x) { thrown = x; throw x; } catch (Error x) { thrown = x; throw x; } catch (Throwable x) { thrown = x; throw new Error(x); } finally { afterExecute(task, thrown); } } finally { task = null; w.completedTasks++; w.unlock(); } } completedAbruptly = false; } finally { processWorkerExit(w, completedAbruptly); } }
如何使用線程池?併發
ThreadPoolExecutor方法的構造參數有不少,咱們看看最長的那個就能夠了:框架
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) throw new IllegalArgumentException(); if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException(); this.acc = System.getSecurityManager() == null ? null : AccessController.getContext(); this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; this.keepAliveTime = unit.toNanos(keepAliveTime); this.threadFactory = threadFactory; this.handler = handler; }
public class ThreadPoolTest { private static final int CORE_POOL_SIZE = 5; //核心線程數 private static final int MAX_POOL_SIZE = 10; //最大線程數 private static final int QUEUE_CAPACITY = 100; //任務隊列的容量 private static final Long KEEP_ALIVE_TIME = 1L; //等待時間 public static void main(String[] args) { ThreadPoolExecutor threadPool = new ThreadPoolExecutor( CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, new ArrayBlockingQueue<>(QUEUE_CAPACITY), new ThreadPoolExecutor.AbortPolicy()); for(int i = 0; i < 10 ; i ++){ Runnable worker = new MyRunnable(""+ i); //建立任務 threadPool.execute(worker); //經過execute提交 } threadPool.shutdown(); while(!threadPool.isTerminated()){ } System.out.println("Finished all threads"); }}class MyRunnable implements Runnable { private String command; MyRunnable(String s) { this.command = s; } @Override public void run() { System.out.println(Thread.currentThread().getName() + " Start. Time = " + new Date()); processCommand(); System.out.println(Thread.currentThread().getName() + " End. Time = " + new Date()); } private void processCommand() { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } } @Override public String toString() { return this.command; }}
固然,也能夠根據須要自定義拒絕策略,須要實現RejectedExecutionHandler。ide
1、使用ThreadPoolExecutor的各類構造方法。工具
2、經過Executor框架的工具類Executors能夠建立三種類型的ThreadPoolExecutor。性能
《阿里巴巴 Java 開發手冊》中強制線程池不容許使用 Executors 去建立,而是經過 ThreadPoolExecutor 的方式,這樣的處理方式讓寫的同窗更加明確線程池的運行規則,規避資源耗盡的風險this
Executors 返回線程池對象的弊端以下: FixedThreadPool 和 SingleThreadExecutor: 容許請求的隊列長度爲 Integer.MAX_VALUE ,可能堆積大量的請求,從而致使 OOM。 CachedThreadPool 和 ScheduledThreadPool : 容許建立的線程數量爲 Integer.MAX_VALUE ,可能會建立大量線程,從而致使 OOM。
threadPool.execute(new Runnable() { @Override public void run() { }}); //經過execute提交
Future<Object> future = threadPool.submit(hasReturnValueTask); try{ Object s = future.get(); }catch(InterruptedException e){ //處理中斷異常 }catch(ExecutionException e){ //處理沒法執行任務異常 }finally{ threadPool.shutdown(); }
若是以爲本文對你有幫助,能夠點贊關注支持一下spa