线程学习笔记(十二)-线程池
2017-08-14 17:20
417 查看
线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程,每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。本实例介绍如何运用线程池实现任务的执行。
技术要点
运用线程池实现任务的执行的技术要点如下:
如果某个线程在托管代码中空闲,则线程池将插入另一个辅助线程(线程池)来使所有处理器保持繁忙;如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则 线程池将在一段时间后创建另一个辅助线程(线程池),但线程的数目永远不会超过最大值。超过最大值的线程可以排队,但它们要等到其他线程完成后后才启动。
任务放在LinkedList中,由于LinkedList不支持同步,所以在添加任务和获取任务的方法声明中必须使用synchronized关键字
关闭线程池时,通过ThreadGroup线程组获得池中所有活动线程的引用,依次调用Thread类的join()方法等待活动线程执行完毕。当所有线程运行结束是,线程池才算被关闭。
源程序解读
(1)TextThreadPool类的createTask()方法根据任务编号执行指定的任务。在类的main()主方法中实例化三个ThreadPool对象作为线程池,Thread类的sleep()方法使线程休眠0.6秒,运用循环执行创建的工作任务,如果没有创建工作任务,则线程池的三个ThreadPool则会一直等待,调用waitTaskFinish()方法等待所有的任务执行完毕再关闭线程池。
(2)内部类ThreadPool继承线程组类ThreadGroup实现线程池的功能。其私有内部类TaskThread继承Thread线程类,扩展run()方法。在run()方法中根据标识为真进行循环。根据Thread类的getTask()方法获得Runnable任务对象,调用任务对象的run()方法执行任务。
(3)ThreadPool类的构造方法传入线程池中工作线程的数量,设置该类为守护线程类,并创建双向链表。运用循环创建任务线程并启动线程。executeTask()方法是往双向链表中添加任务对象并唤醒等待任务的工作任务线程。getTask()方法根据编号获得指定的任务,并移除双向链表中的双向链表中的第一个任务线程。
(4)waitTaskFinish()方法是等待任务线程执行所有的任务。在其同步块中唤醒等待任务的工作任务线程并设置标识为真。根据活动的线程数创建现场数组,根据活动的线程获得线程组中当前所有活动的工作线程,再运用循环通过join()方法等待所有工作线程结束。closeThreadPool()方法判断标识,如果标识为真,则调用waitTaskFinish()方法将等待的任务线程的所有的任务执行完毕。若设置标识为假,清空双向链表中的任务,唤醒线程池中的所有工作线程。
(5) 对于线程池的三个ThreadPool对象运用了wait和notify的方法。在getTask方法中使用wait方法来等待工作任务,等待list元素;exexcuteTask()方法中把工作任务放入list后,便调用notify方法通知线程池的三个ThreadPool对象取工作任务。
技术要点
运用线程池实现任务的执行的技术要点如下:
如果某个线程在托管代码中空闲,则线程池将插入另一个辅助线程(线程池)来使所有处理器保持繁忙;如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则 线程池将在一段时间后创建另一个辅助线程(线程池),但线程的数目永远不会超过最大值。超过最大值的线程可以排队,但它们要等到其他线程完成后后才启动。
任务放在LinkedList中,由于LinkedList不支持同步,所以在添加任务和获取任务的方法声明中必须使用synchronized关键字
关闭线程池时,通过ThreadGroup线程组获得池中所有活动线程的引用,依次调用Thread类的join()方法等待活动线程执行完毕。当所有线程运行结束是,线程池才算被关闭。
package core; import java.util.LinkedList; class ThreadPool extends ThreadGroup { private static int threadPool_ID = 1; // 线程池的编号 private LinkedList<Runnable> taskQueue; // 工作任务队列 private boolean isClosed = false;// 线程池是否关闭 private class TaskThread extends Thread { private int id; public TaskThread(int id) { super(ThreadPool.this, id + "");// 将线程加入到当前线程组中 this.id = id; } public void run() { while (!isInterrupted()) {// 判断线程是否被中断 Runnable task = null; task = getTask(id);// 取出任务 // 如果getTask()返回null或者线程执行getTask()被中断,则结束此线程 if (task == null) return; try { task.run(); // 运行任务 } catch (Throwable t) { t.printStackTrace(); } } } } public synchronized Runnable getTask(int id) { try { while (taskQueue.size() == 0) {// 循环使线程等待任务 if (isClosed) return null; System.out.println("工作线程" + id + "等待任务"); wait();// 如果任务队列中没有任务,就等待任务 } } catch (InterruptedException e) { System.out.println("等待任务出现错误: " + e.getMessage()); } System.out.println("工作线程" + id + "开始执行任务。。。。"); return (Runnable) taskQueue.removeFirst();// 返回第一个任务并从队列中删除 } public ThreadPool(int poolsize) { super(threadPool_ID + " "); setDaemon(true); taskQueue = new LinkedList<Runnable>();// 创建工作任务队列 for (int i = 0; i < poolsize; i++) {// 循环创建任务线程 new TaskThread(i).start();//根据线程池数据创建任务线程并启动线程 } } public synchronized void exexcuteTask(Runnable task){//添加新任务并执行任务 if(isClosed){ throw new IllegalStateException();//抛出不合理状态异常 } if(task !=null){ taskQueue.add(task);//向任务队列中加入一个任务 notify();//唤醒线程池中等待任务的工作任务线程 } } public void waitTaskFinish(){ synchronized(this){ isClosed=true; notifyAll();//唤醒所有等待任务的工作任务线程 } Thread[] threads=new Thread[activeCount()];//创建线程组中活动的线程组 int count=enumerate(threads);//获得线程组中当前所有活动的工作线程 for (int i = 0; i < count; i++) { try { threads[i].join(); } catch (InterruptedException e) { System.out.println("任务执行出错: " + e.getMessage()); } } } public synchronized void closeThreadPool(){//关闭线程池 if(!isClosed){ //判断标识 waitTaskFinish(); //等待任务线程执行完毕 isClosed=true; //标识为真 taskQueue.clear();//任务队列清空 interrupt();//唤醒线程池中所有的工作线程 } } } public class TextThreadPool { private static Runnable createTask(final int taskID) {// 创建任务方法 return new Runnable() { @Override public void run() { System.out.println("任务开始,编号为" + taskID); System.out.println("start task"); System.out.println("任务结束,编号为" + taskID); } }; } public static void main(String[] args) { ThreadPool threadPool=new ThreadPool(3); //初始化创建3个任务线程的线程池,等待执行任务 try {//休眠600毫秒,让线程池中的任务线程全部运行 Thread.sleep(600); } catch (InterruptedException e) { System.out.println("线程休眠出错: "+e.getMessage()); } for (int i = 0; i < 5; i++) { //循环创建并执行任务 threadPool.exexcuteTask(createTask(i)); } threadPool.waitTaskFinish();//等待所有任务执行完毕 threadPool.closeThreadPool();//关闭线程池 } }
源程序解读
(1)TextThreadPool类的createTask()方法根据任务编号执行指定的任务。在类的main()主方法中实例化三个ThreadPool对象作为线程池,Thread类的sleep()方法使线程休眠0.6秒,运用循环执行创建的工作任务,如果没有创建工作任务,则线程池的三个ThreadPool则会一直等待,调用waitTaskFinish()方法等待所有的任务执行完毕再关闭线程池。
(2)内部类ThreadPool继承线程组类ThreadGroup实现线程池的功能。其私有内部类TaskThread继承Thread线程类,扩展run()方法。在run()方法中根据标识为真进行循环。根据Thread类的getTask()方法获得Runnable任务对象,调用任务对象的run()方法执行任务。
(3)ThreadPool类的构造方法传入线程池中工作线程的数量,设置该类为守护线程类,并创建双向链表。运用循环创建任务线程并启动线程。executeTask()方法是往双向链表中添加任务对象并唤醒等待任务的工作任务线程。getTask()方法根据编号获得指定的任务,并移除双向链表中的双向链表中的第一个任务线程。
(4)waitTaskFinish()方法是等待任务线程执行所有的任务。在其同步块中唤醒等待任务的工作任务线程并设置标识为真。根据活动的线程数创建现场数组,根据活动的线程获得线程组中当前所有活动的工作线程,再运用循环通过join()方法等待所有工作线程结束。closeThreadPool()方法判断标识,如果标识为真,则调用waitTaskFinish()方法将等待的任务线程的所有的任务执行完毕。若设置标识为假,清空双向链表中的任务,唤醒线程池中的所有工作线程。
(5) 对于线程池的三个ThreadPool对象运用了wait和notify的方法。在getTask方法中使用wait方法来等待工作任务,等待list元素;exexcuteTask()方法中把工作任务放入list后,便调用notify方法通知线程池的三个ThreadPool对象取工作任务。
相关文章推荐
- [知了堂学习笔记]线程扩展_模拟线程池
- Android开发艺术探索学习笔记6——线程和线程池
- 【学习笔记】多线程编程-线程池/任务/线程
- Java线程和线程池学习笔记
- (48)Java学习笔记——多线程 / 线程间通信 / 线程组 / 线程池 /
- 进程线程等学习笔记
- Linux进程线程学习笔记:进程创建
- Java 线程学习笔记(锁、同步等)
- oracle 学习笔记(十二) oracle独有对象 序列sequence
- RT-Thread 学习笔记(十二)--- 开启基于RTGUI的LCD显示功能(2)<编译测试>
- Java并发学习笔记(11)阻塞线程
- C++ Primer 学习笔记十二 —— 类
- [知了堂学习笔记]线程
- Linux进程线程学习笔记
- Java学习笔记75. 线程的睡眠方法
- python 学习笔记(十二)
- java学习笔记之线程1
- python3.4学习笔记(十二) python正则表达式的使用,使用pyspider匹配输出带.html结尾的URL
- javascript学习笔记(十二) RegExp类型
- 学习笔记 08 --- JUC线程池