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)
集中起来的意志可以击穿顽石

浙公网安备 33010602011771号