首页 技术 正文
技术 2022年11月15日
0 收藏 377 点赞 3,969 浏览 2265 个字

开完一趟车完整的过程是启动、行驶和停车,但老司机都知道,真正费油的不是行驶,而是长时间的怠速、频繁地踩刹车等动作。因为在速度切换的过程中,发送机要多做一些工作,当然就要多费一些油。

而一个Java线程完整的生命周期就包括:

1、T1:创建(启动)

2、T2:运行(行驶)

3、T3:销毁(停车)

而T1 + T3的开销(汽油或者时间)是要远大于T2的。所以,即使是性能再好的车,或者性能再好的计算机,如果经常有T1 + T3的操作存在,那么显然是扛不住的。

所以,为了解决这种因为切换不同线程导致的效率问题,Java推出了线程池技术。通过对已创建线程的合理重用,既能解决上述问题,又能进一步提高响应速度,提升系统性能和稳定性。线程池特别适合下面的应用场景:

1、单个任务处理时间较短

2、需要处理的任务数量大

比如硬件数据采集,像手机、车载和安防传感器的数据采集就特别符合这种情况。

这是线程池相关继承结构图:

很多人都分不清Executor和Executors这两个东西:Executor是接口,是一个根据一组执行策略调用、调度、执行和控制的异步任务框架,提供了一种将“任务提交”与“任务如何运行”分离开的机制。而Executors则是一个工具类(不用new),提供了诸多用于线程池的静态方法。Executor和Executors的关系,和Java I/O中Collection和Collections的关系一毛一样。所以下次再看到XXX和XXXs的时候应该就知道Java的调性了。

说起来还是有点枯燥,那么我拿之前做的一个例子来说一下就明白了。

假设有一个工地有若干项目经理和工人,1个经理+1个工人组成工作小队,工地有很多个这样的工作小队,这些工作小队需要加入项目组,但是只有有活干的才能加入,没活干的加不了,就能要被优化裁员。

/**
* 工人
*/
public class Worker {
/**
* 干活
*/
public void dosomething() {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("挖坑");
}
}
/**
* 经理
*/
public class Manager implements Runnable {
private Worker worker; public Worker getWorker() {
return worker;
} public void setWorker(Worker worker) {
this.worker = worker;
} /**
* 经理动嘴,工人动手
*/
@Override
public void run() {
worker.dosomething();
}
}
/**
* 项目组
*/
public class ManagerGroup {
private static ExecutorService projectGroup = new ThreadPoolExecutor(
3, // 核心小队数量
3, // 最多能容纳多少个小队
30, // 多久没活干就请出项目组
TimeUnit.SECONDS, // 时间单位
new ArrayBlockingQueue<Runnable>(3),// 有多少个项目经理就不再接收入组申请
new ThreadPoolExecutor.CallerRunsPolicy() // 项目组拒绝响应时怎么处理
); // 项目组增加工作小队
public static void addTask(Manager manager) {
projectGroup.execute(manager);
} public static void main(String[] args) {
Manager manager1 = new Manager();
Worker worker1 = new Worker();
manager1.setWorker(worker1); Manager manager2 = new Manager();
Worker worker2 = new Worker();
manager2.setWorker(worker2); Manager manager3 = new Manager();
Worker worker3 = new Worker();
manager3.setWorker(worker3); // 申请进入项目组有活干才可能不被优化
ManagerGroup.addTask(manager1);
ManagerGroup.addTask(manager2);
ManagerGroup.addTask(manager3);
}
}

可以自己将核心小组数量、最多能容纳的小队数量等数字调节一下,然后运行看看效果。

和线程一样,线程池也有自己的状态,而且和线程的状态差不多(想想也是,毕竟要符合线程生命周期的东西,确实应该差不多)。线程池状态:

1、RUNNING:正常运行,能接收新任务,也能处理阻塞队列中的任务;

2、SHUTDOWN:关闭状态,不接收新任务,但可以继续处理阻塞队列中已有任务;

3、STOP:既不接收新任务,也不处理队列中的任务,并会中断正在处理的任务;

4、TIDYING(这个名字叫得有点奇怪):如果所有任务都已中止,且workCount有效线程数为0,则会调用terminated()方法进入TERMINATED状态;

5、TERMINATED:terminated()方法执行完后进入该状态,什么也不做。

线程池运行时的流程图:

至于线程池的构造函数什么的就不多啰嗦了,太枯燥无聊。

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,145
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,617
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,461
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,236
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,871
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,952