二 Java利用等待/通知机制实现一个线程池
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了二 Java利用等待/通知机制实现一个线程池,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4565字,纯文字阅读大概需要7分钟。
内容图文
接着上一篇博客的 一Java线程的等待/通知模型 ,没有看过的建议先看一下。下面我们用等待通知机制来实现一个线程池
线程的任务就以打印一行文本来模拟耗时的任务。主要代码如下:
1 定义一个任务的接口。
1 /* 2 * 任务的接口 3 */ 4 public interface Task { 5 void doSomething(); 6 }
2 实现一个具体的任务。
1 /* 2 * 具体的任务 3 */ 4 public class PrintTask implements Task{ 5 6//打印一句话,睡一秒,来模拟耗时的任务 7 @Override 8publicvoid doSomething() { 9 System.out.println("任务:"+Thread.currentThread().getName()); 10try { 11 Thread.sleep(1000); 12 } catch (InterruptedException e) { 13 e.printStackTrace(); 14 } 15 } 16 }
3 实现工作线程
1 /* 2 * 工作者线程 3 */ 4 public class Worker implements Runnable { 5//线程是否正在运行 6privateboolean running = true; 7 8//保存Thread,方便start() 9private Thread thread; 1011//保存线程池的任务队列,作同步用12private LinkedList<Task> tasks; 1314publicvoid setThread(Thread thread) { 15this.thread = thread; 16 } 1718publicvoid setTasks(LinkedList<Task> tasks) { 19this.tasks = tasks; 20 } 2122//启动此工作线程23publicvoid start() { 24if (thread != null) { 25 thread.start(); 26 } 27 } 2829// 关闭此工作线程30publicvoid shutDown() { 31 running = false; 32 thread.interrupt(); 33 } 3435 @Override 36publicvoid run() { 37while (running) { 38 Task task = null; 3940//对共享变量加锁,此处为任务队列,因为会有多个线程访问41synchronized (tasks) { 4243//当条件不满足时,线程等待,见上一篇博文44while (tasks.isEmpty()) { 45try { 46//线程进入等待状态,并且释放锁47 tasks.wait(); 48 } catch (InterruptedException e) { 49//感知到外部对此线程的中断操作50 Thread.currentThread().interrupt(); 51return; 52 } 53 } 5455//条件满足56 task = tasks.removeFirst(); 57 } 5859//执行任务60if (task != null) { 61 task.doSomething(); 62 } 63 } 64 } 65 }
4 创建一个线程池
1 import java.util.ArrayList; 2 import java.util.LinkedList; 3 import java.util.List; 4 5 public class DefaultThreadPool implements ThreadPool { 6privateint maxWorksNum = 10; 7privateint minWorksNum = 1; 8privateint defaultWorksNum = 5; 9 10// 任务列表 11private LinkedList<Task> tasks = new LinkedList<>(); 12 13// 工作线程列表 14private LinkedList<Worker> workers = new LinkedList<>(); 15 16//工作线程个数 17privateint workerNum = defaultWorksNum; 18 19 20 @Override 21publicvoid excute(Task task) { 22// 添加一个工作,然后进行通知 23if (task != null) { 24synchronized (tasks) { 25//添加到最后一个位置 26 tasks.addLast(task); 27//通知等待的线程,有新的任务了 28 tasks.notify(); 29 } 30 } 31 } 32 33// 关闭线程池 34 @Override 35publicvoid shutDown() { 36for (Worker worker : workers) { 37 worker.shutDown(); 38 } 39 } 40 41// 初始化工作者线程 42publicvoid initWorkers(int num) { 43if (num > maxWorksNum) { 44 num = maxWorksNum; 45 } elseif (num < minWorksNum) { 46 num = minWorksNum; 47 } else { 48 num = defaultWorksNum; 49 } 50 51for (int i = 0; i < workerNum; i++) { 52//创建工作线程 53 Worker worker = new Worker(); 54 55//添加到工作队列 56 workers.add(worker); 57 58//新建一个线程对象,并将worker赋值 59 Thread thread = new Thread(worker); 60 61//设置线程对象,作启动,中断用 62 worker.setThread(thread); 63 64//设置任务队列,作同步用 65 worker.setTasks(tasks); 66 } 67 } 68 69// 启动线程池 70publicvoid start(){ 71if(workers != null){ 72for(Worker worker : workers){ 73//启动一个工作线程 74 worker.start(); 75 } 76 } 77 } 78 79// 新增加工作线程,但是不能大于线程池最大线程数 80 @Override 81publicvoid addWorkers(int num) { 82if (num <= 0) { 83return; 84 } 85 86int remain = maxWorksNum - workerNum; 87if (num > remain) { 88 num = remain; 89 } 90 91for (int i = 0; i < num; i++) { 92 Worker worker = new Worker(); 93 workers.add(worker); 94 Thread thread = new Thread(worker); 95 thread.start(); 96 } 97 98 workerNum = workers.size(); 99 } 100101// 减少工作线程,至少留1个,不能减少到0102 @Override 103publicvoid removeWorkers(int num) { 104if(num >= workerNum || num <= 0){ 105return; 106 } 107108for(int i =0;i<num;i++){ 109 Worker worker = workers.getLast(); 110 worker.shutDown(); 111 } 112113 workerNum = workers.size(); 114 } 115116 @Override 117publicint getTaskSize() { 118return tasks.size(); 119 } 120121122 }
5 新建测试类
1 public class ThreadPoolTest { 2 public static void main(String[] args) throws InterruptedException { 3//1 新建一个线程池 4 DefaultThreadPool pool = new DefaultThreadPool(); 5 6//2 设置线程池的大小为5 7 pool.initWorkers(5); 8 9//3 启动线程池10 pool.start(); 1112//4 往任务队列里面添加任务13for(int i = 0;i<100;i++){ 14 pool.excute(new PrintTask()); 15 } 1617 } 18 }
在eclipse中运行,结果部分截图如下:
好了,一个线程池就这样,这只是一个小例子,提示线程池的原理
其实实现工作中,一个线程池要考虑的问题远比这个多,也更复杂。
其中比较重要的两个方面:
1 线程池开几个线程为最合适?
我们知道,线程不是开的越多越好,而要根据业务的场景,硬件的指标,带宽的大小等等
一般线程池的个数为CPU核心数的个数加1 ,google的建议。此外可能还要具体分析业务
大,中,小的业务需求,也是不一样的。
大任务:比如下载一部电影,可能要十几分钟甚至几十分钟的任务
中任务:比如下载一幅图片,有1M以上了到十几M的大小的。
小任务:比如下载的是游戏的ico,就十几K的到1M以下的。
小任务可以多开几个线程。
中任务的可以保守点。
大任务的尽量不要开的线程太多
具体值还需要看具体业务,具体场景。这些只是建议。
2 线程用哪种队列,也是和上面有关系。
今天就到这了,后续还会抽时间研究线程并发这块,希望对大家有帮忙。
原文:http://www.cnblogs.com/start1225/p/5870072.html
内容总结
以上是互联网集市为您收集整理的二 Java利用等待/通知机制实现一个线程池全部内容,希望文章能够帮你解决二 Java利用等待/通知机制实现一个线程池所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。