使用
ThreadPoolExecutor表示一个线程池。Executors类则扮演着线程池工厂的角色,通过Executors可以获取特定功能的线程池
Executors工厂创建线程池
普通线程池
public static ExecutorService newFixedThreadPool(int nThreads)
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) //提供线程工厂进行创建线程
该方法返回一个固定数量的线程池。该线程池中的线程数量始终不变。
当一个新的任务提交时,线程池中若有空闲线程,则立即执行。若没有,则新的任务被暂时缓冲在任务队列中,待有线程空闲时,便处理任务队列中的任务
public static ExecutorService newSingleThreadExecutor()
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory)
该方法返回只有一个线程的线程池。若有多余的任务被提交到该线程池,任务会被保存在一个任务队列中
public static ExecutorService newCachedThreadPool()
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>());
该方法返回一个可根据实际情况调整线程数量的线程池。线程池的线程数量不确定,若有空闲线程可以复用,则会优先使用可复用的线程。
若所有线程均在工作,又有新的任务提交,则会创建新的线程处理任务,执行完成之后返回线程池进行复用。
看到该方法调用ThreadPoolExecutor方法创建线程池,最大创建的线程数量为Integer.MAX_VALUE,空闲线程的存活时间为60s
普通线程池底层调用
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler)
参数:
corePoolSize:指定了线程池中的核心线程数量
maximumPoolSize:制定了线程池中的最大线程数量
keepAliveTime:当线程池数量超过corePoolSize时,多余的空闲线程的存活时间,即超过corePoolSize的空闲线程,在多长时间内会被销毁
unit:keepAliveTime的单位
workQueue:任务队列,缓存被提交但未被执行的任务
threadFactory: 线程工厂,用于创建线程
handler:拒绝策略,当提交的任务太多缓存队列已满,来不及处理时的拒绝策略
workQueue被提交但未执行的任务队列,它是一个BlockingQueue接口的对象,仅用于存放Runnable对象。
ThreadPoolExecutor类的构造函数可以使用以下几种BlockingQueue接口
1.直接提交的队列:该功能由SynchronousQueue提供
SynchronousQueue是一个特殊的BlockingQueue实现,它没有容量,每一个插入操作都要等待一个相应的删除,反之,每一个删除操作都要等待对应的插入操作。
不会将任务进行保存,而总是将新任务提交给线程执行,如果没有空闲线程,则尝试创建,如果数量已经达到最大值,则执行拒绝策略。因此,使用SynchronousQueue
队列通常要设置很大的maximumPoolSize值,否则很容易执行拒绝策略
2. 有界的任务队列:可以使用ArrayBlockingQueue类实现
ArrayBlockingQueue类的构造函数必须带一个容量参数,表示该队列的最大容量
public ArrayBlockingQueue(int capacity) //构造器
使用有界队列时,当任务队列已满时,才会将线程数提升至corePoolSize以上,当线程数量达到maximumPoolSize时,则执行拒绝策略
3. 无界的任务队列
无界任务队列可以通过LinkedBlockingQueue类实现。
4.优先任务队列
优先任务队列是带有优先级的队列,它的实现有PriorityBlockingQueue类实现,可以控制任务的执行先后顺序。
它是一个特殊的无界队列。
调度线程池
public static ScheduledExecutorService newSingleThreadScheduledExecutor()
public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory)
该方法返回只有一个线程的调度线程池,调度线程池在普通线程池功能上做了一些扩展,如可以固定的延时之后执行,或者周期执行
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
返回一个固定数量线程的调度线程池
调度线程池的扩展方法
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit)
创建一个周期性任务。任务开始于给定的初始延时时。后续的任务按照给定的周期进行
注:当任务执行的时间超过了调度时间时,不会出现任务堆叠的境况,即单次的调度时间为定义的调度时间和实际任务执行的时间中取最大值
注:当任务出现未捕获的异常,则后续的所有子任务都会停止调度
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnit unit)
创建一个周期性任务。任务开始于初始延时时间,后续任务将会按照给定的延时进行:即上一个任务的结束时间到下一个任务的开始时间的时间差
Demo
//固定数量的线程池
public class ThreadPoolDemo {
private static class MyTask implements Runnable{
@Override
public void run() {
System.out.println(System.currentTimeMillis() +":Thread Name:"+Thread.currentThread().getName());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
MyTask task = new MyTask();
ExecutorService es = Executors.newFixedThreadPool(5);
for (int i = 0 ; i< 10 ; i++){
es.submit(task);
}
}
}
public class ScheduledExecutorServiceDemo {
public static void main(String[] args) {
ScheduledExecutorService ses =Executors.newScheduledThreadPool(10);
ses.scheduleAtFixedRate(() -> {
try {
Thread.sleep(1000);
// Thread.sleep(8000); //当任务执行时间超过了调度周期时间,则会按任务执行时间来调度
System.out.println(System.currentTimeMillis()/1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
},0,2, TimeUnit.SECONDS);
}
}
170万+

被折叠的 条评论
为什么被折叠?



