線程池的實現原理
阿新 • • 發佈:2017-08-29
狀態 his color ted except amp bool exc throws
1 package com.test.ThreadPool; 2 3 import java.util.LinkedList; 4 import java.util.List; 5 import java.util.concurrent.atomic.AtomicInteger; 6 /** 7 * 線程池的實現原理 8 * @author Flynn 9 * 10 */ 11 public class ThreadPool { 12 private static ThreadPool pool = null; 13 14 privatefinal int initNum ; //初始化線程數量 15 private volatile AtomicInteger quenLen = new AtomicInteger(0); //任務隊列長度,volatile修飾的原子操作不必加入同步模塊 16 private List<Runnable> taskQuen = new LinkedList<Runnable>() ; //待處理任務隊列,涉及其的操作要做線程安全處理(使用linkedlist是因為任務隊列插入刪除操作比較頻繁) 17 private workThread[] threads;18 private ThreadPool(int num){ 19 this.initNum = num ; 20 threads = new workThread[initNum] ; 21 for(int i=0;i<initNum;i++){ 22 threads[i] = new workThread() ; 23 threads[i].start() ; 24 } 25 } 26 /** 27 * 獲取單例 28 *@param num 29 * @return 30 */ 31 public static ThreadPool getPool(int num){ 32 if(pool == null){ 33 synchronized (ThreadPool.class) { 34 if(pool == null) 35 pool = new ThreadPool(num) ; 36 } 37 } 38 return pool ; 39 } 40 /** 41 * 添加執行任務 42 * @param runs 43 */ 44 public void execute(Runnable...runs){ 45 for(Runnable r : runs){ 46 //操作共享資源任務隊列 需要同步 47 synchronized (taskQuen) { 48 taskQuen.add(r) ; 49 taskQuen.notifyAll() ; 50 } 51 quenLen.incrementAndGet() ; 52 } 53 } 54 public int getTaskNum(){ 55 return quenLen.intValue() ; 56 } 57 public void detory(){ 58 //如果任存在任務,釋放鎖對象並等待20ms再次進入可執行狀態 59 while(!taskQuen.isEmpty()){ 60 try { 61 Thread.sleep(20) ; 62 } catch (InterruptedException e) { 63 // TODO Auto-generated catch block 64 e.printStackTrace(); 65 } 66 } 67 for(int i=0;i<initNum;i++){ 68 threads[i].stopWork() ; 69 threads[i] = null ; //設置為null便於垃圾回收 70 } 71 pool = null ; 72 taskQuen.clear() ; 73 } 74 /** 75 * 內部線程類 76 * @author Flynn 77 * 78 */ 79 private class workThread extends Thread{ 80 private boolean isRunning = true ; //通過此標誌放行線程,也就是說讓線程執行完並銷毀 81 @Override 82 public void run() { 83 // TODO Auto-generated method stub 84 Runnable run = null ; 85 while(isRunning){ 86 synchronized (taskQuen) { 87 //如果沒有任務,釋放鎖對象並等待20ms再次進入可執行狀態 88 while(isRunning && taskQuen.isEmpty()){ 89 try { 90 taskQuen.wait(20) ; 91 } catch (InterruptedException e) { 92 // TODO Auto-generated catch block 93 e.printStackTrace(); 94 } 95 } 96 if(!taskQuen.isEmpty()){ 97 //將任務拿出執行,但不是執行成功如否 98 run = taskQuen.remove(0); 99 quenLen.getAndDecrement(); 100 } 101 } 102 //任務執行,因為沒有涉及到共享資源,不必放入同步模塊 103 if(run!=null){ 104 run.run() ; 105 } 106 run = null ; 107 } 108 } 109 public void stopWork(){ 110 this.isRunning = false ; 111 } 112 } 113 }
1 package com.test.ThreadPool; 2 3 import java.util.concurrent.atomic.AtomicInteger; 4 5 public class TestMain { 6 7 /** 8 * @param args 9 * @throws InterruptedException 10 */ 11 public static void main(String[] args) throws InterruptedException { 12 // TODO Auto-generated method stub 13 ThreadPool pool = ThreadPool.getPool(4) ; 14 new TestMain.myRun() ; 15 pool.execute(new myRun(),new myRun(),new myRun(),new myRun()) ; 16 pool.execute(new myRun(),new myRun(),new myRun(),new myRun()) ; 17 pool.execute(new myRun(),new myRun(),new myRun(),new myRun()) ; 18 pool.execute(new myRun(),new myRun(),new myRun(),new myRun()) ; 19 pool.detory() ; 20 } 21 static class myRun implements Runnable{ 22 private static volatile AtomicInteger len = new AtomicInteger(0); //任務隊列長度,原子操作 23 @Override 24 public void run() { 25 // TODO Auto-generated method stub 26 System.err.println("任務--"+len.incrementAndGet()+"--執行了"); 27 } 28 } 29 }
實驗結果:
1 任務--4--執行了 2 任務--3--執行了 3 任務--1--執行了 4 任務--2--執行了 5 任務--7--執行了 6 任務--6--執行了 7 任務--5--執行了 8 任務--10--執行了 9 任務--9--執行了 10 任務--8--執行了 11 任務--13--執行了 12 任務--12--執行了 13 任務--11--執行了 14 任務--16--執行了 15 任務--15--執行了 16 任務--14--執行了
可以看到16個任務全部執行了,沒有重復,但是打印的順序不是遞增的,那是因為workThread的run()中任務的執行沒有放入同步模塊,這也就是只管將任務執行但不控制它具體執行的時間
線程池的實現原理