抽空自学了一下java线程池工作原理,简单记录一下。
说明:博主由于博客写的比较少,格式不熟练。下文贴的代码格式可能不是很好。
1.线程池的接口实现如下图所示(图片引用别处)
2.线程池的作用
线程池的工作主要是控制运行的线程数量,处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果任务数量超过了最大线程数量,需要进入队列排队等候,等其他线程执行完毕,再从队列中取出任务来执行。
3.主要特点
a.线程复用
b.控制最大并发数量
c.管理线程
4.使用线程池的好处
a.降低了资源消耗。通过复用机制降低了线程创建和销毁的消耗。
b.提高了响应速度。当任务到达时,任务不需要等候就能立即执行。
c.提高了线程的可管理性。线程是稀缺的,如果无限制创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一分配,调优和监控。
5.自己实现线程池
5.1 思考?实现一个线程池需要什么?
-
存放任务的队列或者仓库
-
工作线程,不停的执行任务
-
线程容器,存放工作线程,便于管理
-
阻塞的提交任务方法
-
不阻塞的提交任务方法
-
线程池初始化
-
线程池销毁方法
5.2 源码实现
public class MyThreadPool{
//存放任务的队列或者仓库
private BlockingQueue<Runnable> blockingQueue;
//线程容器,存放工作线程,便于管理
private List<Thread> workers;
//工作线程 需要包装一下
public static class Worker extends Thread{
private MyThreadPool pool;
public Worker(MyThreadPool pool){
this.pool = pool ;
}
@Override
public void run() {
//线程池不是停止状态 或者任务队列有队列时需要工作
while (this.pool.isWorking || this.pool.blockingQueue.size()>0){
Runnable task = null;
try {
if(this.pool.isWorking){
task = this.pool.blockingQueue.take();
}else
task = this.pool.blockingQueue.poll(); //非堵塞
} catch (InterruptedException e) {
e.printStackTrace();
}
if(task !=null){
task.run();
}
}
}
}
//线程池的初始化
public MyThreadPool(int poolsize,int queueSize) {
if(poolsize<0 || queueSize<0){
throw new IllegalArgumentException("非法参数");
}
this.blockingQueue = new LinkedBlockingQueue<>();
this.workers = Collections.synchronizedList(new ArrayList<Thread>());
for(int i=0;i<poolsize;i++){
Worker worker = new Worker(this); // 实例化线程
worker.start(); //开始执行任务
this.workers.add(worker); //加入任务线程
}
}
//提交任务 非阻塞
public boolean submit(Runnable task){
if(isWorking){
if(this.blockingQueue.offer(task)){
return true;
}
}
return false;
}
}
// 提交任务 阻塞
public void execute(Runnable task){
try {
if(isWorking){
this.blockingQueue.put(task);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//线程池的关闭条件
//任务无法加入
//处理完所有任务
//关闭时,不需要阻塞,没有任务需要处理
//关闭时,阻塞得任务需要中断
private volatile boolean isWorking = true;
public void shutDown(){
this.isWorking = false ;
for(Thread th : workers){
if(th.getState().equals(Thread.State.BLOCKED) || th.getState().equals(Thread.State.WAITING) ||
th.getState().equals(Thread.State.TIMED_WAITING)){
th.interrupt();
}
}
}
5.3测试
public static void main(String args[]) throws InterruptedException {
MyThreadPool myThreadPool = new MyThreadPool(3,6);
for (int i=0; i<50; i++){
myThreadPool.submit(new Runnable() {
public void run() {
System.out.println(Thread.currentThread()+"任务正在执行中。。。");
try {
Thread.sleep(2500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
/*Thread.sleep(15000);
myThreadPool.shutDown();*/
}
6.总结
本篇文章实现了一个简单的线程池,但是实际中的线程池工作原理已经和本文很类似了。结合线程池源代码进行阅读。应该可以很快的理解线程池源代码了。