线程池

线程池的创建

public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)

corePoolSize

核心线程数,即线程池的基本大小,当提交一个任务到线程池,线程池会创建一个线程来执行任务,即使其他空闲的基本线程也能执行任务也会创建线程,等到需要执行的任务数大于线程池基本大小时就不再创建。调用线程池的prestartAllCoreThreads()方法,线程池会提前创建并启动所有基本线程。

maximumPoolSize

线程池允许创建的最大线程数

keepAliveTime

线程池的工作线程空闲后,保持存活的时间。如果任务很多,并且每个任务的执行时间很短,可以调大时间,提高线程的利用率。

TimeUnit

keepAliveTime的单位

workQueue

任务队列,用于保存等待任务的阻塞队列
几种BlockingQueue:
直接提交的队列:SynchronousQueue对象提供,总是将新任务提交给线程执行,需要设置很大的maximumPoolSize,否则很容易执行拒绝策略。
有界的任务队列:
public ArrayBlocking(int capacity)
使用有界的任务队列,当线程池中的线程数量小于corePoolSize,创建新线程执行任务,大于corePoolSize,将任务加入到等待队列。若等待队列已满,无法加入,总线程数不大于maximumPoolSize时创建新线程执行任务,若大于maximunPoolSize执行拒绝策略。
无界的任务队列:
LinkedBlockQueue实现。除非系统资源耗尽,无界的任务队列不存在入队失败的问题。当线程池中的线程数量小于corePoolSize,创建新线程执行任务。当线程池中的线程数量达到corePoolSize时,不会继续创建新线程,而是将任务放入任务队列中。
优先任务队列:
PriorityBlockingQueue实现。一个特殊的无界队列。PriorityBlockingQueue可以根据任务自身的优先级顺序先后执行。

拒绝策略handler

任务队列已满,并且线程池中的线程数量达到maximumPoolSize,需要执行拒绝策略。JDK内置提供了4中拒绝策略:
AbortPolicy:抛出异常,默认策略
CallerRunsPolicy:直接在调用者线程中运行当前被丢弃的任务,任务提交线程的性能极有可能会急剧下降
DiscardOldestPolicy:丢弃最老的一个请求,也就是即将被执行的下一个任务,并尝试再次提交当前任务
DiscardPolicy:丢弃无法处理的任务,不予任何执行

线程池任务调度流程:

这里写图片描述

任务提交

线程池框架提供了两种任务提交方式

Executor.execute()

这里写图片描述
通过Executor.execute()方法提交的任务,必须实现Runnable接口,该方式提交的任务不能获取返回值,因此无法判断任务是否执行成功

ExecutorService.submit()

这里写图片描述
通过ExecutorService.submit()方法提交的任务,可以获取任务执行完的返回值。

关闭线程池

可以通过shutdown()或shutdownNow()方法来关闭线程池。原理是遍历线程池中的工作线程,然后逐个调用interrupt()方法来中断线程,无法响应中断的任务可能永远无法终止。

shutdown()

平缓的关闭线程池。线程池停止接受新的任务,同时等待已经提交的任务执行完毕,包括那些进入队列还没有开始的任务。shutdown()方法执行过程中,线程池处于SHUTDOWN状态。

shutdownNow()

立即关闭线程池。线程池停止接受新的任务,同时线程池取消所有执行的任务和已经进入队列但是还没有执行的任务。
shutdownNow()方法执行过程中,线程池处于STOP状态。

线程池扩展

ThreadPoolExecutor提供了三个空方法用于监控线程池的执行情况
protected void beforeExecute(Thread t, Runnable r) { }

protected void afterExecute(Runnable r, Throwable t) { }

protected void terminated() { }

public class ThreadPoolDemo {
    public static class MyTask implements Runnable{
        public String name;
        public MyTask(String name){
            this.name=name;
        }
        @Override
        public void run(){
            System.out.println(System.currentTimeMillis()+":Thread ID:"+Thread.currentThread().getId()+
            ",Task name"+name);
            try{
                Thread.sleep(1000);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args)throws InterruptedException{
        ExecutorService es=new ThreadPoolExecutor(5,5,0L, TimeUnit.MILLISECONDS,new LinkedBlockingDeque<>()){
            @Override
            protected  void beforeExecute(Thread t,Runnable r){
                System.out.println("准备执行:"+((MyTask) r).name);
            }
            @Override
            protected  void afterExecute(Runnable r,Throwable t){
                System.out.println("执行完成:"+((MyTask) r).name);
            }
            @Override
            protected  void terminated(){
                System.out.println("线程池退出");
            }
        };


//        ExecutorService es= Executors.newFixedThreadPool(5);
        for (int i = 0; i <5 ; i++) {
            MyTask task=new MyTask("线程"+i);
            es.execute(task);

        }
        Thread.sleep(2000);
        es.shutdown();
        }
}
准备执行:线程1
准备执行:线程0
1501647585540:Thread ID:10,Task name线程1
1501647585540:Thread ID:9,Task name线程0
准备执行:线程3
1501647585540:Thread ID:12,Task name线程3
准备执行:线程4
1501647585540:Thread ID:13,Task name线程4
准备执行:线程2
1501647585540:Thread ID:11,Task name线程2
执行完成:线程4
执行完成:线程3
执行完成:线程0
执行完成:线程1
执行完成:线程2
线程池退出

Executor框架

Executor框架的3大组成部分
- 任务。包括被执行的任务需要实现的接口:Runnable接口或Callable接口
- 任务的执行。包括任务执行机制的核心接口Executor,以及继承自Executor的ExecutorService接口。Executor框架有两个关键类实现了ExecutorService接口(ThreadPoolExecutor和ScheduledThreadPoolExecutor)
- 异步计算的结果。包括接口Future和实现Future接口的FutureTask类。

这里写图片描述
Executors类扮演着线程池工厂的角色,通过Executors可以取得一个拥有特定功能的线程池。
FixedThreadPool
固定线程数量的线程池,该线程池中的数量始终不变。
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue());
}
SingleThreadExecutor
只有一个线程的线程池,适用于需要保证顺序地执行各个任务。
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue()));
}
CachedThreadPool
线程池的线程数量不确定,若有空闲线程可以复用,优先使用空闲线程,若所有线程均在工作,又有新任务提交,则会创建新线程处理任务。线程在当前任务执行完毕后,将返回线程池中进行复用,空闲线程的存活时间为1分钟。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue());
}
计划任务ScheduledExecutorService
ScheduledThreadPoolExecutor包含若干个线程的ScheduledThreadPoolExecutor
SingleThreadScheduledExecutor包含1个线程的ScheduledThreadPoolExecutor
public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
return new DelegatedScheduledExecutorService
(new ScheduledThreadPoolExecutor(1));
}

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
ScheduledExecutorService可以根据时间对线程进行调度,主要方法如下

public ScheduledFuture<?> schedule(Runnable command,
                                       long delay, TimeUnit unit);
 public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
                                                  long initialDelay,
                                                  long period,
                                                  TimeUnit unit);
 public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
                                                     long initialDelay,
                                                     long delay,
                                                     TimeUnit unit);

schedule()在给定时间对任务进行一次调度;
scheduleAtFixedRate()和scheduleWithFixedDelay()对任务进行周期性的调度,但是两者有一点小小的区别。scheduleAtFixedRate()方法任务调度的频率是一定的,以上一个任务开始执行时间为起点,之后的period时间,调度下一次任务。例如任务执行1秒钟,调度周期是2秒,任务每2秒执行一次。考虑一种情况,调度周期小于任务执行时间,例如任务执行需要8秒,调度周期2秒,ScheduledExecutorService不会让任务堆叠出现,任务的调度周期变为8秒。
scheduleWithFixedDelay()任务开始于初始延时时间,任务结束后经过delay时间执行下一次任务。例如任务执行需要8秒,调度周期2秒,则任务每10秒执行一次。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值