提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
一、什么是线程池
为了避免频繁重复的创建和销毁线程,我们可以让这些线程进行复用,在线程池中,总会有活跃的线程在占用,但是线程池中也会存在没有占用的线程,这些线程处于空闲状态,当有任务的时候会从池子里面拿去一个线程来进行使用,当完成工作后,并没有销毁线程,而是将将线程放回到池子中去。
二、线程池工作原理
ThreadPoolExecutor执行execute方法有4种情况:
1、如果当前运行的线程少于corePoolSize,则创建新的线程来执行任务。
2、如果运行的线程等于或者多余corePoolSize,则将任务加入BlockingQueue中,在等待队列中,等待有新的线程可以运行。
3、如果BlockingQueue队列满了,且没有超过maxPoolSize,则创建新的线程来处理任务。
4、如果创建的线程超过maxPoolSize,任务会拒绝,并调用RejectExecutionHandler.rejectedExecution()方法。
还有以下元素构成:
队列
需要对线程创建和销毁进行管理
ThreadGroup
生产者 —消费者
Wait和notify、以及notifyAll的用法 synchronized
每个对象都有的方法,任何对象都具有同步的功能
Monitor 监视器
Java当中的每个对象都有一个监视器 用于监视并发代码的重入,在非多线程的情况下这个监视器不发挥作用,反之如果在synchronized 的范围内,监视器发挥作用的。
三、自定义线程池的实现
一般我们可以通过ThreadGroup来创建一个线程池:
// 线程池 管理线程对象的容器 使用队列来解决这个问题
// Queue ----LinkedList 线程不安全
// 需要将线程的任务添加到队列中 ,并且自动自动这些任务
// 这些线程都是守护线程
// 核心线程 ---执行 最大线程数量 辅助线程 等待状态
//
// 怎么关闭线程池的问题 ----join
import java.util.LinkedList;
public class ThreadPool extends ThreadGroup{
private boolean isClosed = false;//判断线程池是否需要关闭
private LinkedList taskQueue;
private static int threadPool_ID = 1;
// 负责从工作队列中取出任务并执行的内部类
private class TaskThread extends Thread{
private int id; //任务编号
public TaskThread(int id) {
super(ThreadPool.this, id+"");
this.id= id;
}
@Override
public void run() {
// 判断当前线程是否处于中断状态
while(!isInterrupted()){
Runnable task = null;
// 通过id去获取队列中线程对象
task = getTask(id);
if(task == null)
return;
try{
task.run();
}catch(Exception e){
e.printStackTrace();
}
}
}
}
//线程池的构造方法
public ThreadPool(int poolSize) {
super(threadPool_ID+"");// 规定线程池的名称
setDaemon(true);// 设置守护线程
taskQueue = new LinkedList();//创建队列
//执行线程任务---启动
for (int i = 0; i < poolSize; i++) {
new TaskThread(i).start();
}
}
//添加新任务并且执行
public synchronized void executeTask(Runnable task){
if(isClosed){
throw new IllegalStateException();//
}
if(task !=null){
taskQueue.add(task);// 向任务队列中添加一个任务
notify();//唤醒
}
}
//取任务
private 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 synchronized void closeThreadPool(){
if(!isClosed){// 判断标识
//等待线程任务执行完毕
waitTaskFinish();
isClosed = true;
taskQueue.clear();
interrupt();
}
}
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) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
测试类:
public class ThreadPoolTest {
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);
System.out.println("-----------");
}
};
}
public static void main(String[] args) {
ThreadPool threadpool = new ThreadPool(3);
try {
Thread.sleep(600);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (int i = 0; i < 5; i++) {
threadpool.executeTask(createTask(i));
}
threadpool.waitTaskFinish();
threadpool.closeThreadPool();
}
}
结果:
D:\Java\bin\java.exe "-javaagent:D:\IDEA\IntelliJ IDEA 2019.3.3\lib\idea_rt.jar=60136:D:\IDEA\IntelliJ IDEA 2019.3.3\bin" -Dfile.encoding=GBK -classpath D:\Java\jre\lib\charsets.jar;D:\Java\jre\lib\deploy.jar;D:\Java\jre\lib\ext\access-bridge-64.jar;D:\Java\jre\lib\ext\cldrdata.jar;D:\Java\jre\lib\ext\dnsns.jar;D:\Java\jre\lib\ext\jaccess.jar;D:\Java\jre\lib\ext\jfxrt.jar;D:\Java\jre\lib\ext\localedata.jar;D:\Java\jre\lib\ext\nashorn.jar;D:\Java\jre\lib\ext\sunec.jar;D:\Java\jre\lib\ext\sunjce_provider.jar;D:\Java\jre\lib\ext\sunmscapi.jar;D:\Java\jre\lib\ext\sunpkcs11.jar;D:\Java\jre\lib\ext\zipfs.jar;D:\Java\jre\lib\javaws.jar;D:\Java\jre\lib\jce.jar;D:\Java\jre\lib\jfr.jar;D:\Java\jre\lib\jfxswt.jar;D:\Java\jre\lib\jsse.jar;D:\Java\jre\lib\management-agent.jar;D:\Java\jre\lib\plugin.jar;D:\Java\jre\lib\resources.jar;D:\Java\jre\lib\rt.jar;G:\java\IDEA代码\Test1\out\production\Test1;D:\IDEA\dom4j-1.6.1.jar;D:\IDEA\lib\morph-1.1.1.jar;D:\IDEA\lib\ezmorph-1.0.6.jar;D:\IDEA\lib\commons-lang-2.5.jar;D:\IDEA\lib\json-lib-2.4-jdk15.jar;D:\IDEA\lib\morph-sandbox-1.1.1.jar;D:\IDEA\lib\commons-logging-1.1.1.jar;D:\IDEA\lib\commons-beanutils-1.8.3.jar;D:\IDEA\lib\commons-collections-3.2.1.jar;D:\IDEA\gson-2.2.4.jar;D:\IDEA\mysql-connector-java-5.1.6-bin.jar;D:\IDEA\com.springsource.org.apache.commons.dbcp-1.2.2.osgi.jar;D:\IDEA\com.springsource.org.apache.commons.logging-1.1.1.jar;D:\IDEA\com.springsource.org.apache.commons.pool-1.5.3.jar;D:\IDEA\commons-dbcp-1.4.jar Practice.CSDN.ThreadPoolTest
工作线程0等待任务
工作线程1等待任务
工作线程2等待任务
工作线程0开始执行任务
工作线程2开始执行任务
开了1
start task
开了0
start task
结束0
-----------
结束1
-----------
工作线程1开始执行任务
开了2
工作线程2开始执行任务
start task
结束2
-----------
开了3
start task
结束3
-----------
工作线程0开始执行任务
开了4
start task
结束4
-----------
Process finished with exit code 0