首先要明白線程池的做用,根本做用是維持必定的線程數去執行任務(也會是run方法) 弄明白這一點咱們就能夠寫一個簡易的線程池了 java
首先定義本身的線程池接口 ;安全
package com.MyThread.Mytest; import java.util.List; public interface MyIThreadPool { //執行任務 在執行任務時請確保任務添加完畢; public void execute(); //添加批量任務 public void addTask(List<Runnable> tasks); public void addTask(Runnable task); public void addTask(Runnable[] tasks);
//中途添加任務 當線程池開啓時能夠用該方法添加通常不介意使用
// 我的以爲線程池能夠根據線程大小 維護 多個任務隊列
//每一個線程池取模 到對應任務隊列中獲取;當人本線程中沒有提供此實現ide
public void addSafeTask(List<Runnable> tasks);
//銷燬線程池 建議使用 銷燬前會等待任務完成 public void destory(); //暴露銷燬 不建議使用 可能任務沒完成就直接退出 public void froceDestory(); } //接着已經開頭提到的思想寫出本身的簡易線程池 ,具體代碼以下 package com.MyThread.Mytest; import java.util.LinkedList; import java.util.List; public class MyIThreadPoolImp implements MyIThreadPool { //任務隊列 private List<Runnable> taskqueue = new LinkedList<Runnable>(); //默認開啓線程數量 private static final int defaultNums = 5; private int threadNums; //需設置爲volatile型,當賦值變化時線程能感知 private volatile boolean isRunning = true; //線程數 不會變 不須要維持線程安全 Thread[] taskThreads; private MyIThreadPoolImp() { this(5); } private MyIThreadPoolImp(int num) { if (num <= 0) { threadNums = defaultNums; } else { threadNums = num; } taskThreads = new Thread[threadNums]; for (int i = 0; i < threadNums; i++) { Thread thread = new TaskThread(); thread.setName("TaskThread--" + i); taskThreads[i] = thread; } } public static MyIThreadPool getMyIThreadPool(int num) { return new MyIThreadPoolImp(num); } @Override public void addSafeTask(List<Runnable> tasks) { synchronized (taskqueue) { taskqueue.addAll(tasks); } } //執行任務 @Override public void execute() { for (int i = 0; i < threadNums; i++) { System.out.println(taskThreads[i].getName()+"開啓啦"); taskThreads[i].start(); } } @Override public void addTask(Runnable[] tasks) { for (Runnable task : tasks) { taskqueue.add(task); } } @Override public void addTask(Runnable task) { taskqueue.add(task); } //批量添加任務 @Override public void addTask(List<Runnable> tasks) { taskqueue.addAll(tasks); } @Override public void destory() { while (!taskqueue.isEmpty()) { try { Thread.sleep(20); } catch (Exception e) { System.out.println("請等待任務完成"); e.printStackTrace(); } } isRunning = false; for (int i = 0; i < threadNums; i++) { taskThreads[i] = null; } } @Override public void froceDestory() { isRunning = false; for (int i = 0; i < threadNums; i++) { taskThreads[i].destroy(); } } class TaskThread extends Thread { Runnable runnable = null; @Override public void run() { //當線程池可用 無限循環 while (isRunning) { synchronized (taskqueue) { if (!taskqueue.isEmpty() && isRunning) { runnable = taskqueue.remove(0); } else { try { //等待20後釋放鎖鎖 taskqueue.wait(20); } catch (Exception e) { e.printStackTrace(); ; } } } //記住將runnable置於同步代碼塊外,不然會致使一個線程佔有鎖時間過長 if (runnable != null) { runnable.run(); } } } } } //接下來進行測試 package com.MyThread.Mytest; public class MyThreadPoolTest { public static void main(String[] args){ MyIThreadPool myIThreadPool = MyIThreadPoolImp.getMyIThreadPool(7); for(int i =0 ;i<50;i++){ myIThreadPool.addTask(new MyTask()); } myIThreadPool.execute(); myIThreadPool.destory(); } static class MyTask implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()+"處理了"); } } }
能夠發現咱們用7個線程就完成了咱們50個任務;固然這只是簡單的線程池實現 沒有涉及到複雜的變化,要想更深刻的當即還得去看JDK源碼
測試