Java线程池简单实现

(已迁移)

--  线程池优势:

  不会一个任务一个线程,进而创建以万记的线程量,导致频繁的线程上下文切换,消耗系统资源。且线程的创建和销毁同样浪费着系统资源。

1 public interface JobRun {
2     //Job的具体工作内容
3     void concreteJob();
4 }
 1 import java.util.concurrent.TimeUnit;
 2 
 3 public class Job implements JobRun {
 4     @Override
 5     public void concreteJob(){
 6         System.out.println("执行某一个工作,耗时1s");
 7         try{
 8             TimeUnit.SECONDS.sleep(1);
 9         }catch(InterruptedException e){
10             e.printStackTrace();
11         }
12     }
13 }
 1 public interface ThreadPool<Job extends JobRun> {
 2     //执行一个Job,这个Job需要实现Runnable接口
 3     void execute(Job job);
 4     //关闭线程池
 5     void shutdown();
 6     //增加工作线程
 7     void addWorkers(int num);
 8     //减少工作线程
 9     void removeWorker(int num);
10     //得到正在等待执行的任务数量
11     int getJobSize();
12 }
  1 import java.util.ArrayList;
  2 import java.util.Collections;
  3 import java.util.LinkedList;
  4 import java.util.List;
  5 import java.util.concurrent.atomic.AtomicLong;
  6 
  7 public class DefaultThreadPool<Job extends JobRun> implements ThreadPool<Job> {
  8     //线程池最大限制数
  9     private static final int MAX_WORKER_NUMBERS = 10;
 10     //线程池默认线程数
 11     private static final int DEFAULT_WORKER_NUMBERS = 5;
 12     //线程池最小线程数
 13     private static final int MIN_WORKER_NUMBERS = 2;
 14     //一个工作列表,将会向里面插入工作
 15     private final LinkedList<Job> jobs = new LinkedList<Job>();
 16     //工作者列表
 17     private final List<Worker> workers = Collections.synchronizedList(new ArrayList<Worker>());
 18     //工作者线程数
 19     private int workerNum = DEFAULT_WORKER_NUMBERS;
 20     //线程编号生成
 21     private AtomicLong threadNum = new AtomicLong();
 22 
 23     public DefaultThreadPool(){
 24         initializeWorkers(DEFAULT_WORKER_NUMBERS);
 25     }
 26 
 27     public DefaultThreadPool(int num){
 28         if(num > MAX_WORKER_NUMBERS){
 29             workerNum = MAX_WORKER_NUMBERS;
 30         }
 31         if(num<MIN_WORKER_NUMBERS){
 32             workerNum = MIN_WORKER_NUMBERS;
 33         }
 34         initializeWorkers(workerNum);
 35     }
 36 
 37     public void execute(Job job){
 38         if(job != null){
 39             synchronized (jobs){
 40                 //增加一个工作,然后进行通知
 41                 jobs.addLast(job);
 42                 jobs.notify();
 43             }
 44         }
 45     }
 46 
 47     public void shutdown(){
 48         for(Worker worker : workers){
 49             worker.shutdown();
 50         }
 51     }
 52 
 53     public void addWorkers(int num){
 54         synchronized (jobs){
 55             //限制新增的Worker数量不能超过最大值
 56             if(num + this.workerNum > MAX_WORKER_NUMBERS){
 57                 num = MAX_WORKER_NUMBERS - this.workerNum;
 58             }
 59             initializeWorkers(num);
 60             this.workerNum += num;
 61         }
 62     }
 63 
 64     public void removeWorker(int num){
 65         synchronized (jobs){
 66             if(num >= this.workerNum){
 67                 throw new IllegalArgumentException("beyond workNum");
 68             }
 69             //按照给定的数量停止Worker
 70             int count = 0;
 71             while(count < num){
 72                 Worker worker = workers.get(0);
 73                 if(workers.remove(worker)){
 74                     worker.shutdown();
 75                     ++count;
 76                 }
 77             }
 78             this.workerNum -= count;
 79         }
 80     }
 81 
 82     public int getJobSize(){
 83         return jobs.size();
 84     }
 85 
 86     //初始化线程工作者
 87     private void initializeWorkers(int num){
 88         for(int i =0;i<num;++i){
 89             Worker worker = new Worker();
 90             workers.add(worker);
 91             Thread thread = new Thread(worker,"ThreadPool-worker-" + threadNum.incrementAndGet());
 92             thread.start();
 93         }
 94     }
 95 
 96     //工作者,负责消费任务
 97     class Worker implements Runnable{
 98         //是否工作
 99         private volatile boolean running = true;
100         @Override
101         public void run(){
102             while (running){
103                 Job job = null;
104                 synchronized (jobs){
105                     //如果工作者列表为空,那么wait
106                     while(jobs.isEmpty()){
107                         try{
108                             jobs.wait();
109                         }catch(InterruptedException ex){
110                             //感知到外部对WorkerThread的中断操作,返回
111                             Thread.currentThread().interrupt();
112                             return;
113                         }
114                     }
115                     //取出一个job
116                     job = jobs.removeFirst();
117                 }
118                 if(job != null){
119                     try{
120                         job.concreteJob();
121                     }catch(Exception ex){
122                         System.out.println(ex.getMessage());
123                     }
124                 }
125             }
126         }
127 
128         public void shutdown(){
129             running = false;
130         }
131     }
132 }
 1 public class ApplicationDemo {
 2     public static void main(String[] args){
 3         DefaultThreadPool<Job> defaultThreadPool = new DefaultThreadPool<Job>();
 4         defaultThreadPool.removeWorker(3);
 5         for(int i = 0;i<20;++i){
 6             Job job = new Job();
 7             defaultThreadPool.execute(job);
 8         }
 9     }
10 }

--  关于Collects.synchronizedList

  ArrayList是非线程安全的,多线程下向list插入数据可能会造成数据丢失。并且一个线程变量list,另一个线程修改list,会报ConcurrentModificationException(并发修改异常)错误。

  Vector是线程安全的list,但是它的线程安全实现方式是对所有操作都加上synchronized关键字,这种方式严重影响效率,不推荐使用。

  推荐使用:

 1 List<String> list = Collections.synchronizedList(new ArrayList<String>());
 2 list.add("1");
 3 list.add("2");
 4 list.add("3");
 5 
 6 synchronized(list){
 7     Iterator iter = list.iterator();
 8     while(iter.hasNext()){
 9         System.out.println(iter.next());
10     }
11 }
Collections.synchronizedList会对add方法加锁。
遍历的时候,应避免数据被其他线程串改,应加锁保护。
(但是上文线程池实现的时候,Collections.synchronizedList貌似并非是必要的)

(参考:Java并发编程的艺术)
(参考原文:https://www.cnblogs.com/luojiabao/p/11308803.html)
posted @ 2020-10-18 16:47  α_伊卡洛斯  阅读(154)  评论(0)    收藏  举报