线程池总结

1.为什么要用线程池?

创建线程和线程销毁的开销比较大,占用的时间恐怕要比我们正常业务的时间还要大。而且业务需要可能会频繁的进行创建和销毁,再加上我们本身的业务线程,可能会导致系统资源不足,这种不可控的开销是我们无法接受的。所以我们可以简化这个过程。假如在业务开始之前就维护一组线程,用的时候直接用岂不是很快?

2.线程池的作用

提高效率:如上面说的,业务开始之前我们就维护一个线程池,拿来即用,就像你考试,你做好准备了再考究很轻松效率很高,但是你要临时抱佛脚,那就捉襟见肘了(闲话)

方便管理:上面说过,频繁的进行线程创建和销毁,这样做是不可控的。高并发的情况下,来了一大批请求,难道你要创建一大堆线程吗?分分钟卡死。有了线程池就不一样了,你比如维护了100个线程,现在来了101个请求,你先用100个线程去处理100个请求,把多出来的请求,放进一个等待队列里排队。

3.线程池的使用场景

ThreadPoolExecutor构造方法:


 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

ThreadPoolExecutor参数:

  • corePoolSize: 线程池核心线程数
  • maximumPoolSize:线程池最大数
  • keepAliveTime: 空闲线程存活时间
  • unit: 时间单位
  • workQueue: 线程池所使用的缓冲队列
  • threadFactory:线程池创建线程使用的工厂
  • handler: 线程池对拒绝任务的处理策略

java里面线程池的顶级接口是Executor,但是严格意义上讲Executor并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是ExecutorService

比较重要的几个类:

几个重要的类
ExecutorService真正的线程池接口
ScheduledExecutorService能和Timer/TimerTask类似,解决那些需要任务重复执行的问题
ThreadPoolExecutorExecutorService的默认实现
ScheduledThreadPoolExecutor继承ThreadPoolExecutor的ScheduledExecutorService接口实现,周期性任务调度的类实现

1、newSingleThreadExecutor

创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

看下代码:

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
final int index = i;
singleThreadExecutor.execute(new Runnable() {
 
@Override
public void run() {
try {
System.out.println(index);
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}

2、newFixedThreadPool

创建一个定长的线程池,控制最大的并发线程数,多余的任务放在队列里排队等候

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
final int index = i;
fixedThreadPool.execute(new Runnable() {
 
@Override
public void run() {
try {
System.out.println(index);
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}

3、newCachedThreadPool
 

创建一个可缓存线程池,如果线程池长度超过请求数,回收空闲的线程。若无可回收,则新建线程。示例代码如下

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int index = i;
try {
Thread.sleep(index * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
 
cachedThreadPool.execute(new Runnable() {
 
@Override
public void run() {
System.out.println(index);
}
});
}

4.newScheduledThreadPoo

创建一个线程池,定时周期性的执行

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
scheduledThreadPool.schedule(new Runnable() {
 
@Override
public void run() {
System.out.println("delay 3 seconds");
}
}, 3, TimeUnit.SECONDS);

//表示延迟3秒执行

//例子

scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
 
@Override
public void run() {
System.out.println("delay 1 seconds, and excute every 3 seconds");
}
}, 1, 3, TimeUnit.SECONDS);

参考一篇文章:

Java 四种线程池

4.线程池工作队列

ArrayBlockingQueue是一个基于数组结构的有界阻塞队列,此队列按 FIFO(先进先出)原则对元素进行排序
LinkedBlockingQueue一个基于链表结构的阻塞队列,此队列按FIFO (先进先出) 排序元素,吞吐量通常要高于ArrayBlockingQueue。静态工厂方法Executors.newFixedThreadPool()使用了这个队列
SynchronousQueue一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQueue,静态工厂方法Executors.newCachedThreadPool使用了这个队列
PriorityBlockingQueue一个具有优先级的无限阻塞队列

 

 

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值