標籤:消費 img date pack over lock 處理 介面 core
使用多線程以及線程池的意義無需多說,要想掌握線程池,最好的方法還是自己手動去實現。
一、實現思路
(網路盜圖)
總的來說,所有的任務在BlockingQueue中進行等待,由Worker進行具體的操作,Worker才是真正的背景工作執行緒。
二、代碼
1、線程池類
package com.ty.thread;
import java.util.HashSet;import java.util.Set;import java.util.concurrent.BlockingQueue;import java.util.concurrent.LinkedBlockingQueue;/** * @author Taoyong * @date 2018年5月17日 * 天下沒有難敲的代碼! */public class ThreadPoolExecutor { //維護線程的list private Set<Thread> threadList = new HashSet<Thread>(); /* * 阻塞隊列是安全執行緒的,主要使用在生產/消費者的情境 */ private BlockingQueue<Task> blockingQueue; //線程池的背景工作執行緒數 private int poolSize = 0; //線程池的核心容量 private int coreSize = 0; private boolean shutDown = false; public ThreadPoolExecutor(int size) { this.poolSize = size; blockingQueue = new LinkedBlockingQueue<>(poolSize); } public void execute(Task task) throws InterruptedException { if(shutDown == true) { return; } if(coreSize < poolSize) { blockingQueue.offer(task); produceWorker(task); }else { blockingQueue.put(task); } } private void produceWorker(Task task) throws InterruptedException { if(task == null) { throw new NullPointerException("非法參數:傳入的task對象為空白!"); } if(shutDown == true) { return; } Thread thread = new Thread(new Worker()); threadList.add(thread); coreSize++; thread.start(); }
public void shutDown() { if(threadList == null || threadList.size() == 0) { return; } shutDown = true; for(Thread thread: threadList) { System.out.println(thread.getName() + " interrupt"); thread.interrupt(); } } /* * 此內部類是實際上的工作線 worker是實現了Runnable介面的實際背景工作執行緒,通過while(true)迴圈從BlockingQueue中取任務執行。 * */ class Worker implements Runnable { @Override public void run() { while(true && shutDown == false) { try { blockingQueue.take().doJob(); } catch (InterruptedException e) { e.printStackTrace(); } } } }}
2、Task類(需要被線程處理的任務類)
package com.ty.thread;/** * @author Taoyong * @date 2018年5月17日 * 天下沒有難敲的代碼! */public class Task { //通過taskId對任務進行標識 private int taskId; public Task(int taskId) { this.taskId = taskId; } public void doJob() { System.out.println("線程" + Thread.currentThread().getName() + "正在處理任務!"); } public int getId() { return taskId; }}
3、測試類別
package com.ty.thread;/** * @author Taoyong * @date 2018年5月17日 * 天下沒有難敲的代碼! */public class ThreadPoolExecutorTest { public static void main(String[] args) throws InterruptedException { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3); for(int i = 0; i < 10; i++) { Task task = new Task(i); threadPoolExecutor.execute(task); } threadPoolExecutor.shutDown(); }}
4、運行結果
線程Thread-0正在處理任務!線程Thread-2正在處理任務!線程Thread-0正在處理任務!線程Thread-1正在處理任務!線程Thread-2正在處理任務!線程Thread-2正在處理任務!線程Thread-1正在處理任務!線程Thread-2正在處理任務!線程Thread-0正在處理任務!Thread-1 interruptThread-0 interruptThread-2 interrupt
當第十個任務待處理時,整個線程池已經被shutDown,整個流程結束。
簡單實現java線程池