JAVA——线程池总结

目录

 

我们为什么要用线程池?

如何创建一个线程池?

ThreadPoolExecutor参数含义

1. corePoolSize

2. maximumPoolSize

3. keepAliveTime

4. unit

5. workQueue

6. threadFactory

7. handler

如何使用线程池?

(1)execute

(2)submit

使用完后如何关闭线程池?

(1)shutdown原理:

(2)shutdownNow原理:


我们为什么要用线程池?

线程池的优势
(1) 降低系统资源消耗,通过重用已存在的线程,降低线程创建和销毁造成的消耗;
(2)提高系统响应速度,当有任务到达时,无需等待新线程的创建便能立即执行;
(3)方便线程并发数的管控,线程若是无限制的创建,不仅会额外消耗大量系统资源,更是占用过多资源而阻塞系统或oom 等状况,从而降低系统的稳定性。线程池能有效管控线程,统一分配、调优,提供资源使用率;
(4)更强大的功能,线程池提供了定时、定期以及可控线程数等功能的线程池,使用方便简单。

如何创建一个线程池?

通过ThreadPoolExecutor来创建一个线程池
//不同参数
ExecutorService service = new ThreadPoolExecutor(....);
//七个参数
ExecutorService service = new ThreadPoolExecutor(5, 10, 10, Time Unit.SECONDS, new LinkedBlockingQueue<>());
//线程池的7个参数的构造方法
public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {}

ThreadPoolExecutor参数含义

1. corePoolSize

线程池中的核心线程数,默认情况下,核心线程一直存活在线程池中,即便他们在线程池中处于闲置状态。除非我们将ThreadPoolExecutor 的allowCoreThreadTimeOut属性设为 true 的时候,这时候处于闲置的核心线程在等待新任务到来时会有超时策略,这个超时时间由keepAliveTime 来指定。一旦超过所设置的超时时间,闲置的核心线程就会被终止。

2. maximumPoolSize

线程池中所容纳的最大线程数,如果活动的线程达到这个数值以后,后续的新任务将会被阻塞。包含核心线程数+ 非核心线程数。

3. keepAliveTime

非核心线程闲置时的超时时长,对于非核心线程,闲置时间超过这个时间,非核心线程就会被回收。只有对ThreadPoolExecutor allowCoreThreadTimeOut 属性设为true 的时候,这个超时时间才会对核心线程产生效果。

4. unit

用于指定 keepAliveTime 参数的时间单位。他是一个枚举,可以使用的单位有:
天 (TimeUnit.DAYS ),
小时( TimeUnit.HOURS ),
分钟(TimeUnit.MINUTES ),
毫秒( TimeUnit.MILLISECONDS)
微秒(TimeUnit.MICROSECONDS, 千分之一毫秒),
毫微秒(TimeUnit.NANOSECONDS, 千分之一微秒);

5. workQueue

线程池中保存等待执行的任务的阻塞队列。通过线程池中的 execute 方法提交的Runable对象都会存储在该队列中。我们可以选择下面几个阻塞队列。

6. threadFactory

线程工厂,为线程池提供新线程的创建。 ThreadFactory 是一个接口,里面只有一个newThread 方法。 默认为 DefaultThreadFactory 类。

7. handler

RejectedExecutionHandler 对象,而 RejectedExecutionHandler 是一个接口,里面只有一个rejectedExecution 方法。当任务队列已满并且线程池中的活动线程已经达到所限定的最大值或者是无法成功执行任务,这时候ThreadPoolExecutor 会调用RejectedExecutionHandler 中的 rejectedExecution 方法。在ThreadPoolExecutor中有四个内部类实现了 RejectedExecutionHandler 接口。在线程池中它默认是AbortPolicy ,在无法处理新任务时抛出 RejectedExecutionException 异常。
下面是在 ThreadPoolExecutor 中提供的四个可选值。

如何使用线程池?

可以通过 execute submit 两种方式来向线程池提交一个任务。

(1)execute

当我们使用 execute 来提交任务时,由于 execute 方法没有返回值,所以说 我们也就无法判定任务是否被线程池执行成功。
 
service.execute(new Runnable() { 
    public void run() { 
        System.out.println("execute方式"); 
    } 
});

(2)submit

当我们使用 submit 来提交任务时 , 它会返回一个 future, 我们就可以通过这个 future 来判断任务是否执行成功,还可以通过future get 方法来获取返回值。如果子线程任务没有完成,get 方法会阻塞住直到任务完成,而使用 get(long timeout, TimeUnit unit)方法则会阻塞一段时间后立即返回,这时候有可能任务并没有执行完。
Future<Integer> future = service.submit(new Callable<Integer>() { 
    @Override 
    public Integer call() throws Exception { 
        System.out.println("submit方式"); 
        return 2; 
    } 
}); 
try {
    Integer number = future.get(); 
} catch (ExecutionException e) { 
    // TODO Auto-generated catch block e.printStackTrace(); 
}

使用完后如何关闭线程池?

线程池关闭
调用线程池的 shutdown() shutdownNow() 方法来关闭线程池

(1)shutdown原理:

将线程池状态设置成 SHUTDOWN 状态,然后中断所有没有正在执行任务的线程。

(2)shutdownNow原理:

将线程池的状态设置成 STOP 状态,然后中断所有任务 ( 包括正在执行的) 的线程,并返回等待执行任务的列表。
中断采用 interrupt 方法,所以无法响应中断的任务可能永远无法终止。 但调用上述的两个关闭之一,isShutdown() 方法返回值为 true ,当所有任务都已关闭,表示线程池关闭完成,则isTerminated() 方法返回值为 true 。当需要立刻中断所有的线程,不一定需要执行完任务,可直接调用shutdownNow() 方法。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值