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 ...
随机推荐
- HashMap实现缓存(二)
package com.cache; import java.util.*; //Description: 管理缓存 //可扩展的功能:当chche到内存溢出时必须清除掉最早期的一些缓存对象,这就要求 ...
- 使用SQL Server 2008 维护计划(图解)
使用Sql Server 2008的维护计划可以实现自动备份数据库,并自动删除过期备份的功能. 一.环境 OS: Microsoft Windows Server 2003 R2 soft:Micro ...
- WIN32 窗口类封装 框架实现部分
上面已经讲了窗口封装部分,内容可点击:http://www.cnblogs.com/mengdejun/p/4010320.html,下面分享框架部分内容,完成WINDOWS消息迭代 CQFrameW ...
- ThinkPHP3.* 模型操作相关函数
ThinkPHP3.* 版本,大家所不熟知的,且与数据库操作相关的函数做以简单罗列: 1.getLastSql 别名 _sql (鉴于getLastSql比较常用,故出现了别名函数_sql) 2.se ...
- C语言两种查找方式(分块查找,二分法)
二分法(必须要保证数据是有序排列的): 分块查找(数据有如下特点:块间有序,块内无序):
- 科学计算软件——Octave安装
Octave是一个旨在提供与Matlab语法兼容的开放源代码科学计算及数值分析的工具,是Matlab商业软件的一个强有力的竞争产品. 参考:[ML:Octave Installation] Gener ...
- 在.NET Core中遭遇循环依赖问题"A circular dependency was detected"
今天在将一个项目迁移至ASP.NET Core的过程中遭遇一个循环依赖问题,错误信息如下: A circular dependency was detected for the service of ...
- Hadoop学习笔记—15.HBase框架学习(基础实践篇)
一.HBase的安装配置 1.1 伪分布模式安装 伪分布模式安装即在一台计算机上部署HBase的各个角色,HMaster.HRegionServer以及ZooKeeper都在一台计算机上来模拟. 首先 ...
- iOS开发系列—Objective-C之Foundation框架
概述 我们前面的章节中就一直新建Cocoa Class,那么Cocoa到底是什么,它和我们前面以及后面要讲的内容到底有什么关系呢?Objective-C开发中经常用到NSObject,那么这个对象到底 ...
- 简单一招实现json数据可视化
开发一个内部功能时碰到的需求,要把json数据在页面上展示出来,平时浏览器会安装jsonView这样的扩展来看json数据,但是程序要用到的话该怎么办呢?今天在网上搜索的时候,发现了这个小技巧,分享一 ...