多线程-Executors和Executor,线程池

多线程-Executors和Executor,线程池,第1张

线程-Executors和Executor,线程池

jdk1.5之前,所有的线程都是需要自己手动创建的,由jvm销毁,当请求过多的时候,频繁的创建和销毁线程是非常浪费资源的。


jdk1.5为此做了优化,提供了

java.util.concurrent

包,该包下有个 Executor 接口,官方解释为:

执行已提交的 Runnable 任务的对象。


此接口提供一种将任务提交与每个任务将如何运行的机制(包括线程使用的细节、调度等)分离开来的方法。


通常使用 Executor 而不是显式地创建线程。


很明显,有这个这个东西,我们不需要自己手动 new Thread了。


程序员只需要专注于任务就可以了,然后把任务交给executor,由他帮我们执行任务。


因此,我们可以非常自然的想到一个东西,那就是 线程池,ThreadPoolExecutor就是该接口的具体实现类。


我们的具体的线程池实现类。


public class ThreadPoolExecutor extends AbstractExecutorService

实现了通用的管理线程的方法。



public abstract class AbstractExecutorService implements ExecutorService

ExecutorService抽象了基本的管理线程的方法,如提交任务,关闭任务。



public interface ExecutorService extends Executor

而线程池有几个主体,线程管理器(线程池本身),工作线程(workThread)任务(runnable),等待队列


简单来说,线程管理器维护一定数量的工作线程,将我们提交的任务交由工作线程完成,当池中没有空闲的工作线程时,交给等待队列中去。


等待队列可以是先进先出,先进后出,具体策略由你自己来决定。


当等待队列也慢了的时候,我们

当创建线程池时几个参数包含了线程池的一切

corePoolSize:
核心线程池数,线程池默认的工作线程数,线程池创建时,默认为0,只有来一个任务才创建一个线程。


maximumPoolSize:
线程池允许的最多线程数,当等待队列满了之后,这个参数才有意义。


keepAliveTime:
当池中的线程数大于核心线程数时,多余的线程在销毁之前会等待指定时间。


unit:
多余的线程等待的时间单位。


workQueue:
当核心线程数全部都在运行任务时,再次来的任务将被放到该等待队列中。


此队列仅保持由 execute 方法提交的 Runnable 任务。



举个栗子来说名线程池根据参数运行的流程:
corePoolSize:5
maximumPoolSize:15(包含corePoolSize)
keepAliveTime:2
unit:秒
workQueue:数组型等待队列,最大的等待数为50

1.当我创建5个线程时,线程池将会一一创建核心线程数,
2.当第6个任务来临,而前面5个任务还没有完成是,线程池中没有线程了,那么线程池将会把这个任务放到任务workQueue中。



3.当第56个线程来临时,而核心线程还在运行,而workQueue中也已经饱和。


此时,线程池会多创建一个线程来运行多出来的那一个任务
(具体哪一个任务根据你的策略来)。


但是池中的线程数不能超过maximumPoolSize,包含核心数。



4.当第66个任务来临的时候,池中已经有15个线程在运行任务了,等待队列中也已经有50个线程在等待,因此 15+50=65 是ok的,但是再来一个66的
话那就不ok了,线程池直接回拒接你,抛出 RejectedExecutionException 错误。



测试代码如下:
public class Worker extends Thread {

private int i = 0;

@Override
public void run() {

while(i==0){
i++;
try {
Thread.currentThread().sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" run...");
}

}
}

//等待队列最大任务数为50
ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue<Runnable>(50);
//核心线程数:5 最大线程数:15 多余线程存活时间:2秒
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5,15,2,TimeUnit.SECONDS,arrayBlockingQueue);
// threadPoolExecutor.prestartAllCoreThreads();
System.out.println("池中的当前线程数 :" + threadPoolExecutor.getPoolSize());

//创建56个任务。



for(int i = 0 ; i < 65; i ++){
threadPoolExecutor.execute(new Worker());
}
System.out.println("==================over===============");

ArrayBlockingQueue<Runnable> blockingQueue = (ArrayBlockingQueue)threadPoolExecutor.getQueue();

System.out.println("池中的当前线程数 :" + threadPoolExecutor.getPoolSize());
System.out.println("曾经同时位于池中的最大线程数 :" + threadPoolExecutor.getLargestPoolSize());
System.out.println("等待队列中的任务数:" + blockingQueue.size());

输出:
池中的当前线程数 :0
==================over===============
池中的当前线程数 :15
曾经同时位于池中的最大线程数 :15
等待队列中的任务数:50
pool-1-thread-2  run...
pool-1-thread-5  run...
.....
Executors类中包含了很多静态方法创建多种不同类型的线程池。



1.创建可伸缩线程池。



2.创建定长线程池。



3.创建定长线程池,支持执行定制和周期性任务。



3.创建单例线程的线程池。



参考资料:
http://www.importnew.com/19011.html
http://blog.csdn.net/hsuxu/article/details/8985931
http://cuisuqiang.iteye.com/blog/2019372
---------------------
作者:helianus
来源:CSDN
原文:https://blog.csdn.net/helianus/article/details/78304733
版权声明:本文为博主原创文章,转载请附上博文链接!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/589169.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-12
下一篇 2022-04-12

发表评论

登录后才能评论

评论列表(0条)

保存