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 ...
随机推荐
- jquery插件-表单验证插件-validator对象
三 Validator对象 1.介绍:Validate方法返回的对象称作Validator对象 2.使用 Validator对象常用方法 Validator.form() 返回:Boolean 验证: ...
- http80端口转发(实现微信公众号接口绑定IP时,同时支持多个公众号)
http80端口转发 背景 微信公众平台接口绑定服务器时,如果使用IP需要使用80端口,此组件可实现一个IP上绑定多个公众平台接口 使用方法 http://(IP)/WeixinMP/(转发的地址Ba ...
- 在打开vs解决方案时,怎样让所以打开的项目自动折叠
使用VS 2010中的扩展性,搜PowerCommands,PowerCommands扩展在Visual Studio 2010中添加了数十个有用的的命令, Collapse Projects(折叠项 ...
- java循环遍历map
import java.util.HashMap; import java.util.Iterator; import java.util.Map; public class MapTest { pu ...
- C#调用c++的dll报错:“尝试读取或写入受保护的内存。这通常指示其他内存已损坏“
一:c++代码内部报错引起.可能是空指针或者其他. 二:需要从c#代码调试进入c++代码.可以吧c++的dll和pdb拷入工程项目的debug目录下面. 三:我发现的错误时在C++内部声明啦全局变量, ...
- 屠蛟之路_重伤的屠蛟俊_ThirdDay
在屠蛟少年们重登数据库大山的途中,少年屠蛟俊(511)实力扛把子,一直坚持在队伍前头开路引领.披荆斩棘,却也因为一路与险水恶林.狂禽猛兽做战斗而精力受损,最终一不小心坠进beta怪蛟设置的陷阱深洞里, ...
- ruby 淘宝镜像
由于国内GFW原因,导致无法安装gem库文件.故选择淘宝镜像, 如何使用? $ gem sources --remove https://rubygems.org/ $ gem sources -a ...
- python group()
正则表达式中,group()用来提出分组截获的字符串,()用来分组 #!/usr/bin/python import re line = "Cats are smarter than dog ...
- A/D转换实验
实验效果:
- C#中使用代码动态改变配置文件信息
static void Main(string[] args) { XmlDocument xDoc = new XmlDocument(); xDoc.Load("../../App.co ...