线程池原理

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


一、什么是线程池

为了避免频繁重复的创建和销毁线程,我们可以让这些线程进行复用,在线程池中,总会有活跃的线程在占用,但是线程池中也会存在没有占用的线程,这些线程处于空闲状态,当有任务的时候会从池子里面拿去一个线程来进行使用,当完成工作后,并没有销毁线程,而是将将线程放回到池子中去。

二、线程池工作原理

在这里插入图片描述

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值