Java并发编程核心方法与框架-Executors的使用
合理利用线程池能够带来三个好处
- 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
- 提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
- 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
官方建议使用Executors工厂类来创建线程池对象
使用newCachedThreadPool()方法创建无界线程池
使用Executors类的newCachedThreadPool()方法创建的是无界线程池,可以进行线程自动回收。所谓的“无界线程池”就是池中存放线程个数理论上是Integer.MAX_VALUE。
public class Run1 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(new Runnable() {
@Override
public void run() {
try {
System.out.println("Runnable1 begin:" + System.currentTimeMillis());
Thread.sleep(1000);
System.out.println("A");
System.out.println("Runnable1 end:" + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
executorService.execute(new Runnable() {
@Override
public void run() {
try {
System.out.println("Runnable2 begin:" + System.currentTimeMillis());
Thread.sleep(1000);
System.out.println("A");
System.out.println("Runnable2 end:" + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
程序运行结果如下:
Runnable1 begin:1470228063076
Runnable2 begin:1470228063076
A
A
Runnable2 end:1470228064081
Runnable1 end:1470228064081
线程池的线程复用效果
public class MyRunnable implements Runnable {
private String username;
public MyRunnable(String username) {
super();
this.username = username;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " username=" + username + " begin:" + System.currentTimeMillis());
System.out.println(Thread.currentThread().getName() + " username=" + username + " end:" + System.currentTimeMillis());
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++) {
executorService.execute(new MyRunnable("" + i));
}
Thread.sleep(2000);
System.out.println();
for (int i = 0; i < 5; i++) {
executorService.execute(new MyRunnable("" + i));
}
}
}
程序运行结果如下:
pool-1-thread-1 username=0 begin:1470229448635
pool-1-thread-4 username=3 begin:1470229448635
pool-1-thread-3 username=2 begin:1470229448635
pool-1-thread-2 username=1 begin:1470229448635
pool-1-thread-3 username=2 end:1470229448635
pool-1-thread-4 username=3 end:1470229448635
pool-1-thread-5 username=4 begin:1470229448635
pool-1-thread-1 username=0 end:1470229448635
pool-1-thread-5 username=4 end:1470229448636
pool-1-thread-2 username=1 end:1470229448635
pool-1-thread-1 username=2 begin:1470229450637
pool-1-thread-3 username=4 begin:1470229450637
pool-1-thread-3 username=4 end:1470229450637
pool-1-thread-2 username=0 begin:1470229450637
pool-1-thread-2 username=0 end:1470229450638
pool-1-thread-5 username=1 begin:1470229450637
pool-1-thread-4 username=3 begin:1470229450637
pool-1-thread-4 username=3 end:1470229450638
pool-1-thread-5 username=1 end:1470229450638
pool-1-thread-1 username=2 end:1470229450637
由打印结果可见,第一次for循环中创建了5个线程对象分别是pool-1-thread-1到pool-1-thread-5,第二次for循环中没有创建新的线程对象,复用了第一次for循环中创建的线程对象。
使用newCachedThreadPool(ThreadFactory)定制线程工厂
public class MyThreadFactory implements ThreadFactory {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setName("定制池中线程对象的名称" + Math.random());
return thread;
}
}
public class Run {
public static void main(String[] args) {
MyThreadFactory myThreadFactory = new MyThreadFactory();
ExecutorService executorService = Executors.newCachedThreadPool(myThreadFactory);
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "运行:" + System.currentTimeMillis());
}
});
}
}
程序运行结果如下:
定制池中线程对象的名称0.2671917944865071运行:1470230269473
使用newFixedThreadPool(int)方法创建有界线程池
public class MyRunnable implements Runnable {
String username;
public MyRunnable(String username) {
super();
this.username = username;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " username=" + username + " begin:" + System.currentTimeMillis());
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() + " username=" + username + " end:" + System.currentTimeMillis());
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class Run {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
for (int i = 0; i < 3; i++) {
executorService.execute(new MyRunnable("" + i));
}
for (int i = 0; i < 3; i++) {
executorService.execute(new MyRunnable("" + i));
}
}
}
程序运行结果如下:
pool-1-thread-1 username=0 begin:1470230865037
pool-1-thread-3 username=2 begin:1470230865037
pool-1-thread-2 username=1 begin:1470230865037
pool-1-thread-3 username=2 end:1470230867043
pool-1-thread-1 username=0 end:1470230867042
pool-1-thread-3 username=0 begin:1470230867043
pool-1-thread-1 username=1 begin:1470230867043
pool-1-thread-2 username=1 end:1470230867043
pool-1-thread-2 username=2 begin:1470230867043
pool-1-thread-3 username=0 end:1470230869047
pool-1-thread-1 username=1 end:1470230869047
pool-1-thread-2 username=2 end:1470230869047
此时线程池中最多有三个线程。
使用newFixedThreadPool(int, ThreadFactory)定制线程工厂
public class MyThreadFactory implements ThreadFactory {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setName("定制池中线程对象的名称" + Math.random());
return thread;
}
}
public class Run {
public static void main(String[] args) {
MyThreadFactory threadFactory = new MyThreadFactory();
ExecutorService executorService = Executors.newFixedThreadPool(2, threadFactory);
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
System.out.println("begin 我在运行" + System.currentTimeMillis() + " " + Thread.currentThread().getName());
Thread.sleep(2000);
System.out.println("end 我在运行" + System.currentTimeMillis() + " " + Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
executorService.execute(runnable);
executorService.execute(runnable);
executorService.execute(runnable);
}
}
程序运行结果如下:
begin 我在运行1470231214770 定制池中线程对象的名称0.07643716796315236
begin 我在运行1470231214770 定制池中线程对象的名称0.5060032203497645
end 我在运行1470231216773 定制池中线程对象的名称0.5060032203497645
end 我在运行1470231216773 定制池中线程对象的名称0.07643716796315236
begin 我在运行1470231216773 定制池中线程对象的名称0.5060032203497645
end 我在运行1470231218774 定制池中线程对象的名称0.5060032203497645
使用newSingleThreadExecutor()方法创建单一线程池
public class MyRunnable implements Runnable {
String username;
public MyRunnable(String username) {
super();
this.username = username;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " username=" + username + " begin:" + System.currentTimeMillis());
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() + " username=" + username + " end:" + System.currentTimeMillis());
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class Run {
public static void main(String[] args) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
for (int i = 0; i < 3; i++) {
executorService.execute(new MyRunnable("" + i));
}
}
}
程序运行结果如下:
pool-1-thread-1 username=0 begin:1470231470978
pool-1-thread-1 username=0 end:1470231472978
pool-1-thread-1 username=1 begin:1470231472978
pool-1-thread-1 username=1 end:1470231474982
pool-1-thread-1 username=2 begin:1470231474982
pool-1-thread-1 username=2 end:1470231476984
此时线程池中只有一个线程。
newSingleThreadExecutor(ThreadFactory) 使用方法与前面的大体一致。
Java并发编程核心方法与框架-Executors的使用的更多相关文章
- Java并发编程核心方法与框架-CountDownLatch的使用
Java多线程编程中经常会碰到这样一种场景:某个线程需要等待一个或多个线程操作结束(或达到某种状态)才开始执行.比如裁判员需要等待运动员准备好后才发送开始指令,运动员要等裁判员发送开始指令后才开始比赛 ...
- Java并发编程核心方法与框架-TheadPoolExecutor的使用
类ThreadPoolExecutor最常使用的构造方法是 ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAli ...
- Java并发编程核心方法与框架-Fork-Join分治编程(一)
在JDK1.7版本中提供了Fork-Join并行执行任务框架,它的主要作用是把大任务分割成若干个小任务,再对每个小任务得到的结果进行汇总,这种开发方法也叫做分治编程,可以极大地利用CPU资源,提高任务 ...
- Java并发编程核心方法与框架-CompletionService的使用
接口CompletionService的功能是以异步的方式一边生产新的任务,一边处理已完成任务的结果,这样可以将执行任务与处理任务分离.使用submit()执行任务,使用take取得已完成的任务,并按 ...
- Java并发编程核心方法与框架-Semaphore的使用
Semaphore中文含义是信号.信号系统,这个类的主要作用就是限制线程并发数量.如果不限制线程并发数量,CPU资源很快就会被耗尽,每个线程执行的任务会相当缓慢,因为CPU要把时间片分配给不同的线程对 ...
- Java并发编程核心方法与框架-ScheduledExecutorService的使用
类SchedukedExecutorService的主要作用是可以将定时任务与线程池功能结合. 使用Callable延迟运行(有返回值) public class MyCallableA implem ...
- Java并发编程核心方法与框架-ExecutorService的使用
在ThreadPoolExecutor中使用ExecutorService中的方法 方法invokeAny()和invokeAll()具有阻塞特性 方法invokeAny()取得第一个完成任务的结果值 ...
- Java并发编程核心方法与框架-Future和Callable的使用
Callable接口与Runnable接口对比的主要优点是Callable接口可以通过Future获取返回值.但是Future接口调用get()方法取得结果时是阻塞的,如果调用Future对象的get ...
- Java并发编程核心方法与框架-CyclicBarrier的使用
CyclicBarrier类似于CountDownLatch也是个计数器,不同的是CyclicBarrier数的是调用了CyclicBarrier.await()进入等待的线程数,当线程数达到了Cyc ...
随机推荐
- yii的csv导出
数据导出,简单的csv导出, public static function export($parameter){ if (is_array($parameter)) { $filename = da ...
- Python % 格式化字符串
格式字符串 python 使用一个字符串作为模板 模板中含有格式符,为真实值预留位置 使用tuple或者字典来传递值 模板和值之间,用 % 来表示格式化操作 例子: 1) tuple 传值 print ...
- 【BZOJ-1055】玩具取名 区间DP
1055: [HAOI2008]玩具取名 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1560 Solved: 907[Submit][Statu ...
- 使用Jayrock开源组件开发基于JSON-RPC协议的接口
最近接手一个以前的项目,无意间发现此项目开发接口的组件:Jayrock(接口组件估计用的少,用的最多的估计是这个Jayrock.json.dll,用于解析json) 以下是Jayrock的介绍官网: ...
- phpMyadmin /scripts/setup.php Execute Arbitrary PHP Code Via unserialize Vul Object Injection PMASA-2010-4
目录 . 漏洞描述 . 漏洞触发条件 . 漏洞影响范围 . 漏洞代码分析 . 防御方法 . 攻防思考 1. 漏洞描述 对这个漏洞简单的概括如下 . "/scripts/setup.php&q ...
- waf2控件名
1,查询表格(queryGrid),编辑表格(editGrid) wafGrid 2,快速F7 wafPromptQuick 3,表格F7 wafPromptGrid 4,自定义F7 wafPromp ...
- Pipe
#一边压缩一边传 一边解压 到对方的目录为/tlj/2/ / | ssh root@172.16.200.56 tar xzf - -C /tlj #在一个需要文件名的地方 使用-重定向输出到stdo ...
- Centos下 为Firefox安装Flash插件
方法一: 直接到官网去下载RPM格式的安装包,下载好后直接 用 rpm -ivh XXXX.rpm 来安装即可. 方法二: 到官网下载tar.gz格式的,自己配置安装: #wget http://fp ...
- PTA fzu_oop_east
GitHub链接: 传送门 5-1该日是该年的第几天 定义一个日期类Date,内有数据成员年.月.日,另有成员函数:构造函数用于初始化数据成员,输出,闰年的判断. 编写主函数:创建日期对象,计算并输出 ...
- 感受身边app
第一款:高考小秘书.http://www.liqucn.com/rj/519571.shtml.下载链接.我认为产品最大的优势在于对高考生非常有利,实用价值大,对于每年的高考生来说,高考资讯和大学资讯 ...