线程池的特点:

降低资源:通过重复利用已创建的线程降低线程创建和销毁的损耗

提高效率:当任务到底时,不需要等待,立即执行

方便管理:统一分配,调优和监控等

线程池的创建方式:

1.CachedThreadPool:创建一个可缓存线程池,灵活回收空闲线程

public class ThreadPoolDemo {
public static void main(String[] args) {
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int temp = i;
newCachedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "->" + temp);
}
});
}
}
}

打印后可以发现:同一个线程有被再次利用,线程池理论大小是无限的

2.FixedThreadPool:创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待

        ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(5);

其他代码不变,打印发现五个线程都在复用

3.ScheduledThreadPool:支持定时性地执行任务

public class ThreadPoolDemo {
public static void main(String[] args) {
ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(5);
for (int i = 0; i < 10; i++) {
final int temp = i;
newScheduledThreadPool.schedule(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "->" + temp);
}
}, 3, TimeUnit.SECONDS);
}
}
}

观察打印:等待3s后打印

4.SingleThreadExecutor:单线程

        ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();

打印发现只调用了一个线程

线程池的原理:

四种方式都走了ThreadPoolExecutor的构造方法:

    public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
    public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}

corePoolSize:最大核心线程数:实际运用线程数

maximumPoolSize:最大线程数:线程池最多创建线程数

如果当前线程池中的线程数目小于corePoolSize,则每来一个任务,就会创建一个线程去执行这个任务

如果当前线程池中的线程数目>=corePoolSize,则每来一个任务,会尝试将其添加到任务缓存队列当中,若添加成功,则该任务会等待空闲线程将其取出去执行;若添加失败(一般来说是任务缓存队列已满),则会尝试创建新的线程去执行这个任务;

如果队列已经满了,则在总线程数不大于maximumPoolSize的前提下,则创建新的线程;

如果当前线程池中的线程数目达到maximumPoolSize,则会采取任务拒绝策略进行处理;

如果线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止,直至线程池中的线程数目不大于corePoolSize;如果允许为核心池中的线程设置存活时间,那么核心池中的线程空闲时间超过keepAliveTime,线程也会被终止。

写一段代码来理解:

public class MyThreadPool {
public static void main(String[] args) {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
//核心线程数为1
1,
//最大线程数为2
2,
//保持存活时间0毫秒,意思是用完不回收
0L, TimeUnit.MILLISECONDS,
//阻塞队列
new LinkedBlockingQueue<Runnable>(3));
threadPoolExecutor.execute(new TaskThread("task1"));
threadPoolExecutor.execute(new TaskThread("task2"));
threadPoolExecutor.execute(new TaskThread("task3"));
}
} class TaskThread implements Runnable {
private String threadName; TaskThread(String threadName) {
this.threadName = threadName;
} @Override
public void run() {
System.out.println(threadName);
}
}

提交task1时候,创建一个线程直接执行,此时核心线程数等于存在线程数

提交task2时候,存放在队列缓存,此时存在线程数等于最大线程数

提交task3时候,也存放在队列中缓存,而我阻塞队列大小是3,现在只存放了两个,所以不会报错

理论上,提交到task5都不会报错,最大线程数2+队列大小3=5;但是提交task6一定会报错

另外一点:如果提交到task4,打印线程名称:发现只调用了线程1,第2个线程没有调用过

因为:task1提交时候,task2,task3,task4存放在队列中,恰好到达队列最大值,所以不创建新线程,而是线程1依次执行这三个任务

合理配置线程池:

原则:

CPU密集:任务需要大量的运算,但没有阻塞的情况,CPU可以全速运行

IO密集:任务需要大量的IO操作,产生阻塞

CPU密集型线程数越少越好,最好配置为CPU核心数量

IO密集型线程数要尽量多,最好配置为CPU核心数量*2

最新文章

  1. kindeditor4整合SyntaxHighlighter,让代码亮起来
  2. JqueryEasyUI之DataGrid扩展
  3. xss跨站攻击测试代码
  4. JAVA数据类型自动转换,与强制转换
  5. C++ STL find
  6. 矩阵分解(rank decomposition)文章代码汇总
  7. EC读书笔记系列之18:条款47、48
  8. hdoj 1226 超级password 【隐图BFS】
  9. android布局中画线的方法
  10. ffmpeg最全的命令参数
  11. .NET Core TDD 前传: 编写易于测试的代码 -- 缝
  12. 4.13Python数据处理篇之Matplotlib系列(十三)---轴的设置
  13. 2018工业信息安全技能大赛华东赛区初赛 第2题 writeup
  14. ivew Tooltip
  15. bootstrap timepicker 在angular中取值赋值 并转化为时间戳
  16. 2016年 CodePen 最热门的前端代码 Top 100
  17. 使用ssh服务管理远程主机
  18. java命令分析线程死锁以及内存泄漏
  19. oracle 之 基础操作
  20. ASP.NET MVC3控制器传递匿名对象到视图实例

热门文章

  1. ActiveMQ传输协议
  2. 【oracle】select into from 和 insert into select 的用法和区别
  3. [无效]网络流之Edmond-Karp算法
  4. 【BZOJ4722】由乃
  5. luoguP2039 [AHOI2009]跳棋 巧妙的dp
  6. 2018-2019-2 20165313 《网络对抗技术》 Exp 9 Web安全基础
  7. 第6课 nullptr_t和nullptr
  8. MVC发布出现:未能将文件bin\xxx.xml 复制到 obj\Release\PackageTmp\bin\xxx.xml,未能找到文件
  9. ASP.NET Core WebApi基于JWT实现接口授权验证
  10. Plsql 破解 非密钥版