Concurrent Programming ——Thread Pool

Concurrent Programming

Concurrent Programming —— Introduction
Concurrent Programming —— Pessimistic Lock and Monitor
Concurrent Programming —— JMM(Java Memory Model)
Concurrent Programming ——Thread Pool
Concurrent Programming —— JUC(java.util.concurrent)

前言

本文将介绍线程池相关知识
频繁的创建和启动线程会带来很大的消耗,导致系统效率降低,因此在多并发的情况,往往会使用线程池的技术来减小消耗

在这里插入图片描述

1.线程池

在这里插入图片描述
线程池的基本设计思路就如上图所示,创建多个线程放在线程池中,当有任务来的时候,将任务分配给一个线程,当没有任务时,线程会在阻塞队列(Blocking Queue)中,等待任务,而当任务过多,没有足够的线程来处理任务时,任务就会被放入阻塞队列中等待线程来执行,线程池是消费者/生产者模式

1.1 ThreadPoolExecutor

Java提供了线程池实现类ThreadPoolExecutor
线程池状态:
ThreadPoolExecutor 使用int的高3位来表示线程池状态,低29位表示线程数量,一共有5中状态

状态高三位
Running111
ShutDown000
Stop001
Tidying010
Terminated011

其中Tidying表示任务全部执行完毕,活动线程为0即将进入Terminated的状态,这些信息都存储在一个原子变量ctl

//构造方法
public ThreadPoolExecutor (int corePoolSize,
						   int maxmimumPoolSize,
						   long keepAliveTIme,
						   TimeUnit unit,
		BlockingQueue<Runnable> workQueue,
		ThreadFactory threadFactory,
		RejectedExecutionHandler handler
)

corePoolSize:核心线程数目(最多保留的线程数)
maxmimumPoolSize:最大线程数目
keepAliveTIme:生存时间 — 针对救急线程
unit:时间单位 — 针对救急线程
workQueue:阻塞队列
threadFactory:线程工厂 - 可以为线程创建时起名字
handler:拒绝策略

当任务过多,线程池中核心线程不够时,线程池会创建出救急线程来完成协助任务,当任务完成后,这些救急线程就会被销毁,keepAliveTIme就是用来用设置这些救急线程生命周期的

拒绝策略:
在这里插入图片描述
Java中提供来4个拒绝策略
DiscardPolicy:放弃本次任务
DiscardOldestPolicy:放弃队列中最早的任务,本次任务取而代之
CallerRunsPolicy:让调用者运行任务
AbortPolicy:让调用者抛出RejectedExecutionException异常,这是默认策略

当任务队列容量满了以后就会触发拒绝策略

Exectuors类中提供了多种线程工厂方法来创建不同种类的线程池

1.2 newFixedThreadPool

newFixedThreadPool的核心线程数等于最大线程数,因此这种线程池没有救急线程,适合固定任务数,且不会繁忙的情况,因为是核心线程,执行完任务不会自己结束线程

//构造方法
public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

1.3 newCachedThreadPool

newCachedThreadPool(带缓冲功能的线程池)
核心线程数是0,最大线程数是Integer.MAX_VALUE,创建的全是救急线程,生存时间是60s,救急线程可以无限创建,队列采用了synchronousQueue实现,没有容量限制,适合任务密集,且每个任务执行时间短的情况

//构造方法
public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

1.4 newSingleThreadExecutor

newSingleThreadExecutor适用于,多个任务希望按照队列顺序来执行,即使碰到异常,也会创建一个新的线程来执行剩下的任务

//构造方法
public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

1.5 线程池常用方法

//执行任务
public void execute(Runnable command);
//提交任务tak,用返回值Future获得任务执行的结果
<T> Future<T> submit(Callable<T> task);
//提交tasks中所有任务,带时限(不传入timeout 和 unit就是不带时限的方法)
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,long timeout, TimeUnit unit)throws InterruptedException;
//执行所有任务,有一个任务执行完毕,就返回该任务的结果,并取消其它任务
<T> T invokeAny(Collection<? extends Callable<T>> tasks)
        throws InterruptedException, ExecutionException;

//关闭线程池
void shutdown();//修改线程池状态,打断空闲线程,尝试终结

//线程池状态变为STOP,不会接受新任务,将队列中的任务返回,用interrupt方法中断正在执行的任务
//会修改线程池状态,打断所有线程,获取队列中剩余任务,尝试终结
void shutdownNow();

1.6 线程池大小选择

线程池过小导致线程不能充分地利用系统资源,容易导致饥饿,过大导致更多的线程上下文切换,占用更多内存,根据不同的情况来决定线程池大

CPU密集型运算(例如:数据分析):
采用 CPU核数+1 能够实现最优的CPU利用率, +1保证来当线程由于页缺失故障或者其它问题导致暂停时,额外的这个线程能够顶上去,保证CPU时钟周期不被浪费

IO密集型:
CPU不总是处于繁忙状态
经验公式:
线程数 = 核数 * 期望CPU利用率 * 总时间(CPU计算时间+等待时间)/CPU计算时间

1.7 Fork/Join线程池

使用了分治思想,适用于进行任务拆分的CPU密集型运算,在分治的基础上加入了多线程,把每个任务的分解和合并交给不同的线程来完成,进一步提升了运算效率

默认创建于CPU核心数相同的线程池

使用方法:

//task对象要先继承RecursiveTask<T>对象
class Task extends RecursiveTask<T>

//重写compute方法
@Override
protected T compute(){
}

Concurrent Programming

Concurrent Programming —— Introduction
Concurrent Programming —— Pessimistic Lock and Monitor
Concurrent Programming —— JMM(Java Memory Model)
Concurrent Programming ——Thread Pool
Concurrent Programming —— JUC(java.util.concurrent)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值