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 ...
随机推荐
- dede使用方法----如何调用最新文章,最热文章,友情链接
dede如何调用最新文章 {dede:arclist row='5' titlelen='50' orderby ='pubdate'} <li><a h ...
- 谷歌console开发人员官方文档(注意是谷歌)
https://developers.google.com/web/tools/chrome-devtools/debug/console/console-ui?hl=en#opening-the-c ...
- python3 异常处理
什么是异常 Python用异常对象(exception object)来表示异常情况.遇到错误会引发异常,如果异常对象未被处理或者捕捉,程序就会用回溯(traceback)终止执行. Raise语句: ...
- WPF弹出取消确定框
MessageBoxResult dr = MessageBox.Show("是否在"+ConfigHelper.GetAppSetting("SourceDBName& ...
- angularjs 手动加载
利用ng-app可以完成自动加载,如果不利用ng-app.那么使用bootstrarp实现手动加载模块 <html> <head> <script src="a ...
- install docker on xubuntu
ref: https://docs.docker.com/engine/installation/linux/ubuntulinux/#/install-the-latest-version ps: ...
- POJ3468 A Simple Problem with Integers
Description 给出了一个序列,你需要处理如下两种询问. "C abc"表示给[a, b]区间中的值全部增加c (-10000 ≤ c ≤ 10000). "Q ...
- Markdown编辑器简单总结
字体大小: #1 ##2 添加链接: 文字链接 [blog](http://yalantis.com/blog/how_we_created_tab_bar_animation_for_ios/?ut ...
- MVC5-5 Razor引擎及视图结构
View结构 其实给我们提供了官方的MvcDemo,就是在我们直接去新建一个不为空的MVC项目. 这里就是一个MVC的Demo了,可以看一下这个Demo中View的结构是什么 上图可以发现,有一个Sh ...
- Server 对象
如何解决Response.Redirect方法传递汉字丢失或乱码问题? 为了确保传递的汉字被正确地接收,可以在传值之前使用Server对象的UrlEncode方法对所传递的汉字进行URL编码.代码如下 ...