【JAVA】手写线程池

1.手写之前首先展示一张原理图:

【JAVA】手写线程池_第1张图片

这里面有几个核心点:

⑴线程池里的核心线程数与最大线程数
⑵线程池里真正工作的线程worker
⑶线程池里用来存取任务的队列BlockingQueue

顺便补充点阻塞队列的知识:

 

add        增加一个元索                     如果队列已满,则抛出一个IIIegaISlabEepeplian异常
remove   移除并返回队列头部的元素    如果队列为空,则抛出一个NoSuchElementException异常
element  返回队列头部的元素             如果队列为空,则抛出一个NoSuchElementException异常
offer       添加一个元素并返回true       如果队列已满,则返回false
poll         移除并返问队列头部的元素    如果队列为空,则返回null
peek       返回队列头部的元素             如果队列为空,则返回null
put         添加一个元素                      如果队列满,则阻塞
take        移除并返回队列头部的元素     如果队列为空,则阻塞

⑷线程中的任务task

 

2.实现

本例实现简化了一些,只实现了BlockingQueue存放任务,然后每个worker取任务并执行,这当然是最简单实现,JDK的实现比这强大的多,而且还具备当工作线程处理不过来时,可以产生新的线程来处理任务,这个数量不能超过原先定义的最大线程数,而在本例中都没实现这些功能。另外没有对任务队列和线程池加锁,这样是线程不安全的,

 

package doThreadPool;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import antlr.collections.List;

public class ThreadExcutor {
   private volatile boolean RUNNING=true;
   //阻塞队列
   private static BlockingQueue queue=null;
   //对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。
   private final HashSet workers = new HashSet();
   
   private final ArrayList threadList = new ArrayList();
   
   
   int poolSize = 0;
   
   int coreSize = 0;

   boolean shutdown = false;
   
   //构造函数,
   public ThreadExcutor(int poolSize){
       this.poolSize = poolSize;
       queue = new LinkedBlockingQueue(poolSize);
   }
   
   public void exec(Runnable runnable) {
       if (runnable == null) throw new NullPointerException();
       if(coreSize < poolSize){         
           addThread(runnable);                
       }else{
           //System.out.println("offer" +  runnable.toString() + "   " + queue.size());
           try {
               queue.put(runnable);                //coreSize>poolSzie 加入阻塞队列中去
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
   }
   
   public void addThread(Runnable runnable){
       coreSize ++;                                 //正在工作的线程+1
       Worker worker = new Worker(runnable);        //
       workers.add(worker);                         
       Thread t = new Thread(worker);              
       threadList.add(t);                          
       try {
           t.start();
       }catch (Exception e){
           e.printStackTrace();
       }

   }

   public void shutdown() {
       RUNNING = false;
       if(!workers.isEmpty()){
           for (Worker worker : workers){
               worker.interruptIfIdle();
           }
       }
       shutdown = true;
       Thread.currentThread().interrupt();
   }
	
   class  Worker implements Runnable{

       public Worker(Runnable runnable){
           queue.offer(runnable);                  //将这个runable将入到队列中去
       }

       @Override
       public void run() {
           while (true && RUNNING){
               if(shutdown == true){
                   Thread.interrupted();
               }
               Runnable task = null;
               try {
                   task = getTask();
                   task.run();
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }
       }

       public Runnable getTask() throws InterruptedException {
           return queue.take();                   
       }

       public void interruptIfIdle() {
           for (Thread thread :threadList) {
               System.out.println(thread.getName() + " interrupt");
               thread.interrupt();
           }
       }
	
}}

 

package doThreadPool;

public class TheadBlockedQ {
	 public static void main(String[] args) throws InterruptedException {
	        ThreadExcutor excutor = new ThreadExcutor(3);
	        for (int i = 0; i < 10; i++) {
	            excutor.exec(new Runnable() {
	                @Override
	                public void run() {
	                    System.out.println("线程 " + Thread.currentThread().getName() + " 在帮我干活");
	                }
	            });
	        }
	       excutor.shutdown();
	    }
}


输出:

 

 

线程 Thread-0 在帮我干活
线程 Thread-1 在帮我干活
线程 Thread-1 在帮我干活
线程 Thread-2 在帮我干活
线程 Thread-0 在帮我干活
线程 Thread-1 在帮我干活
线程 Thread-1 在帮我干活
线程 Thread-1 在帮我干活
线程 Thread-2 在帮我干活
线程 Thread-0 在帮我干活
Thread-0 interrupt
Thread-1 interrupt
Thread-2 interrupt
Thread-0 interrupt
Thread-1 interrupt
Thread-2 interrupt
Thread-0 interrupt
Thread-1 interrupt
Thread-2 interrupt

 

 

 

 

 

 


 

你可能感兴趣的:(JAVA多线程技术)