java使用Executor(执行器)管理线程
一.一个实现了Runnable接口的类
class MyThread implements Runnable{
private static int num = 0;
@Override
public void run() {
while(true){
synchronized(MyThread.class){
++num;
try{
Thread.sleep(500);
} catch(Exception e){
System.out.println(e.toString());
}
System.out.println(Thread.currentThread().getName() + " " + num);
}
}
}
}
1. newCachedThreadPool()方法
CacheThreadPool会为每一个任务创建一个线程。非常常见的情况是,单个的Executor被用来创建和管理系统中的任务。shutdown()方法可以防止新的任务被提交给这个Executor。如果在shutdown()方法之后提交新任务,则会抛出java.util.concurrent.RejectedExecutionException异常。
public class Main{
public static void main(String[] args){
ExecutorService exes = Executors.newCachedThreadPool();
for(int i=0; i<5; ++i)
exes.execute(new MyThread());
exes.shutdown();
}
}
2.FixedThreadPool()方法
FixedThreadPool使用了优先的线程集来执行所提交的任务。有了它,你就可以一次性预先执行代价高的线程分配。也就是说如果设置的最大线程数量是x,而提交的线程数y,那么(y-x)对应的这些线程要等到前x个线程执行完毕才会执行。
下面的例子中,线程6一直不会有机会执行。因为run()方法中是 while(true), 可以将while(true)去掉,前5个线程执行完毕后,才会执行第6个线程。
public class Main{
public static void main(String[] args){
ExecutorService exes = Executors.newFixedThreadPool(5);
for(int i=0; i<6; ++i)
exes.execute(new MyThread());
exes.shutdown();
}
}
3.newSingleThreadExecutor()方法
public class Main{
public static void main(String[] args){
ExecutorService exes = Executors.newSingleThreadExecutor();
for(int i=0; i<5; ++i)
exes.execute(new MyThread());
exes.shutdown();
}
SingleThreadExecutor就像是线程数量为1的FixedThreadPool。这对于你希望在另一个线程中连续运行的事物(长期存活的任务)来说,都是很有用的。如果想SingleThreadExecutor提交了多个任务,那么这些任务将排队,每个任务都会在下一个任务开始之前结束,所有的任务将使用相同的线程。
二.一个实现了Callable<E>接口的类(从任务中产生返回值)
class MyThread implements Callable<String>{
private static int num = 0;
@Override
public String call() throws Exception {
for(int i=0; i<5; ++i){
synchronized(MyThread.class){
++num;
Thread.sleep(200);
System.out.println(Thread.currentThread().getName() + " " + num);
}
}
return Thread.currentThread().getName() + " success!";
}
}
1.ExecutorService.submit()方法
public class Main{
public static void main(String[] args){
ExecutorService exes = Executors.newCachedThreadPool();
ArrayList<Future<String>> rets = new ArrayList<Future<String>>();
for(int i=0; i<5; ++i)
rets.add(exes.submit(new MyThread()));
for(Future<String> fs : rets){
try {
System.out.println(fs.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
submit()会产生Future对象,它用Callable返回结果的特定类型进行了参数化。可以调用Future的isDone()方法来查询Future是否已经完成。调用Future的get()方法来获取最终线程的执行结果。另外,Future的get()方法是一个阻塞方法,直到结果准备就绪。
三.线程的优先级
class MyThread implements Runnable{
private int priority;
public MyThread(){
}
public MyThread(int priority){
this.priority = priority;
}
private static int num = 0;
private volatile double d;
@Override
public void run() {
Thread.currentThread().setPriority(priority);
while(true){
for(int i=0; i<100000; ++i){
d += (Math.PI+Math.E)/(double)i;
if(i%1000 == 0)
Thread.yield();
}
synchronized(MyThread.class){
++num;
try{
Thread.sleep(500);
} catch(Exception e){
System.out.println(e.toString());
}
System.out.println(Thread.currentThread().getName() + " " + num);
}
}
}
}
public class Main{
public static void main(String[] args){
ExecutorService exes = Executors.newCachedThreadPool();
for(int i=0; i<5; ++i)
exes.execute(new MyThread(Thread.MIN_PRIORITY));
exes.execute(new MyThread(Thread.MAX_PRIORITY));
exes.shutdown();
}
}
volatile变量保证编译器对循环不进行任何的优化,如果不加入这些运算的话,就不会看到设置线程优先级的效果。数学运算是可以中断的,向控制台打印不能被中断。这里预案算时间足够的长,因此线程调度机制才来的及介入,交换任务并关注优先级,是的最高优先级被优先选择。
四.后台线程
class SimpleDaemons implements Runnable{
@Override
public void run() {
while(true){
try{
TimeUnit.MILLISECONDS.sleep(200);
System.out.println(Thread.currentThread().getName());
} catch(InterruptedException e){
System.out.println(Thread.currentThread().getName() + " : InterruptException!");
e.printStackTrace();
}
}
}
}
public class Main{
public static void main(String[] args) throws InterruptedException{
for(int i=0; i<10; ++i){
Thread daemon = new Thread(new SimpleDaemons());
daemon.setDaemon(true);
daemon.start();
}
System.out.println("All daemons started");
TimeUnit.MILLISECONDS.sleep(1000);
}
}
所谓后台线程,是指程序运行的时候在后台提供一种通用的服务的线程,并且这种线程并不属于程序中不可或缺的部分。因此,当所有的非后台线程结束时,程序也就终止了,同时会杀死进程中的所有的后台线程。反过来说,只要任何非后台线程还在运行,程序就不会终止。
通过定制自己的ThreadFactory, 可以定制有Executor创建的线程的属性(后台,优先级,名称)
class DaemonThreadFactory implements ThreadFactory{
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
}
class DaemonFromFactory implements Runnable{
@Override
public void run() {
try{
TimeUnit.MILLISECONDS.sleep(100);
System.out.println(Thread.currentThread().getName());
} catch (InterruptedException e){
e.printStackTrace();
}
}
}
public class Main{
public static void main(String[] args) throws InterruptedException{
ExecutorService exes = Executors.newCachedThreadPool(new DaemonThreadFactory());
for(int i=0; i<5; ++i)
exes.execute(new DaemonFromFactory());
System.out.println("All Daemos Started!");
TimeUnit.MILLISECONDS.sleep(1000);
}
}
java使用Executor(执行器)管理线程的更多相关文章
- Java的Executor框架和线程池实现原理
Java的Executor框架 1,Executor接口 public interface Executor { void execute(Runnable command); } Executor接 ...
- java笔记--用ThreadLocal管理线程,Callable<V>接口实现有返回值的线程
用ThreadLocal管理线程,Callable<V>接口实现有返回值的线程 ThreadLocal在我的笔记"关于线程同步"的第5种方式里面有介绍,这里就不多说了. ...
- Java的Executor框架和线程池实现原理(转)
ExecutorService接口继承自Executor接口,定义了终止.提交,执行任务.跟踪任务返回结果等方法 1,execute(Runnable command):履行Ruannable类型的任 ...
- 使用Executor管理线程
上一篇博客(第一个并发程序:定义任务和驱动任务)中,我们使用Thread对象启动线程,而java.util.concurrent包的Executor执行器提供了更好的管理Thread对象的方法,从而简 ...
- Java多线程——<三>简单的线程执行:Executor
一.概述 按照<Java多线程——<一><二>>中所讲,我们要使用线程,目前都是显示的声明Thread,并调用其start()方法.多线程并行,明显我们需要声明多个 ...
- java并发编程(十七)Executor框架和线程池
转载请注明出处:http://blog.csdn.net/ns_code/article/details/17465497 Executor框架简介 在Java 5之后,并发编程引入了一堆新的启动 ...
- 转:【Java并发编程】之十九:并发新特性—Executor框架与线程池(含代码)
Executor框架简介 在Java5之后,并发编程引入了一堆新的启动.调度和管理线程的API.Executor框架便是Java 5中引入的,其内部使用了线程池机制,它在java.util.coc ...
- Java 并发编程——Executor框架和线程池原理
Eexecutor作为灵活且强大的异步执行框架,其支持多种不同类型的任务执行策略,提供了一种标准的方法将任务的提交过程和执行过程解耦开发,基于生产者-消费者模式,其提交任务的线程相当于生产者,执行任务 ...
- 【Java并发编程】:并发新特性—Executor框架与线程池
Executor框架简介 在Java5之后,并发编程引入了一堆新的启动.调度和管理线程的API.Executor框架便是Java 5中引入的,其内部使用了线程池机制,它在java.util.cocur ...
随机推荐
- 第2章 新手必须掌握的Linux命令
第2章 新手必须掌握的Linux命令 章节简述: 本章节讲述系统内核.Bash解释器的关系与作用,教给读者如何正确的执行Linux命令以及常见排错方法. 经验丰富的运维人员可以恰当的组合命令与参数 ...
- JNI和NDK编程
Java JNI的本意是Java Native Interface(Java本地接口),它是为了方便Java调用C.C++等本地代码所封装的一层接口.通过Java JNI,用户可以调用C.C++所编写 ...
- <input>和<textarea>
作为一个刚刚涉足PHP开发的菜鸟,第一次使用博客.在这里分享一些经验给和需要的朋友,互相探讨.共同学习,希望对你有所帮助. 废话不多说,下面进入正题. 应该有朋友和我一样,需要用到文本框,要求它会自动 ...
- IntelliJ IDEA - 热部署插件JRebel 安装使用教程
IntelliJ IDEA - JRebel 安装使用教程 JRebel 能做什么? JRebel 是一款热部署插件.当你的 Java-web 项目在 tomcat 中 run/debug 的时候 , ...
- css选择器万年不变的优先级和权重
我们在使用CSS对网页元素定义样式时经常会遇到这种情况:要对一般元素应用一般样式,然后在更特殊的元素上覆盖它们.那么我们怎么样来保证我们所新定义的元素样式能覆盖目标元素上原有的样式呢? 在CSS中,会 ...
- TPC-H生成.tbl文件导入postgresql数据库的坑
数据库project好好的不用主流的MySQL和Microsoft server而要求用听都没听过的postgresql (当然,可能你三个都没听过) 这里的坑主要是把生成的那八张.tbl的表导入pg ...
- UnderScore源代码阅读1
读一下underscore源代码,用于自己学习,个人理解,如果有不对的地方希望指正,谢谢 我觉着阅读的顺序按照从整体到局部,从架构到细节较好. 1.整体架构 (function() {}.call(t ...
- poj3187-Backward Digit Sums(枚举全排列)
一,题意: 输入n,sum,求1~n的数,如何排列之后,相邻两列相加,直到得出最后的结果等于sum,输出1~n的排列(杨辉三角) 3 1 2 4 //1~n 全排列中的一个排列 4 3 6 7 ...
- CSDN:你认为一名优秀的技术人应该具备怎样的素质?
CSDN:你认为一名优秀的技术人应该具备怎样的素质? 王晶昱:我个人认为,符合这个世界要求的就是优秀的.在目前这个时代,我认为一个优秀的技术人员的特质可能是: 兴趣驱动,兴趣是最好的老师,写程序本身就 ...
- ASP.NET MVC 路由(四)
ASP.NET MVC路由(四) 前言 在前面的篇幅中我们讲解路由系统在MVC中的运行过程以及粗略的原理,想必看过前面篇幅的朋友应该对路由有个概念性的了解了,本篇来讲解区域,在读完本篇后不会肯定的让你 ...