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 ...
随机推荐
- Shader实例:扭曲,漩涡
效果: 案例:新仙剑,王者之剑. 在切换场景的时候,就会有这样的全屏扭曲效果. 思路: 1.用GrabPass抓屏到一张纹理中. 2.进行扭曲,绘制到UGUI的Image上. 准备: 去官网下载Uni ...
- AFNetWorking设置HTTPRequestHeaders的坑
今天在项目中要封装一个请求头但是用如下方法总是失败: 求其原因不知道: 于是乎改用了属性对象后居然成功了..: // // RequestManager.m // 获取天气demo // // ...
- ViewHolder优化2>:
ViewHoder优化: @Override public View getView(int position, View convertView, ViewGroup par ...
- BFS/DFS算法介绍与实现(转)
广度优先搜索(Breadth-First-Search)和深度优先搜索(Deep-First-Search)是搜索策略中最经常用到的两种方法,特别常用于图的搜索.其中有很多的算法都用到了这两种思想,比 ...
- redis配置文件英译汉
# By default Redis asynchronously dumps the dataset on disk. This mode is # good enough in many appl ...
- extern用法总结
在C语言中,修饰符extern用在变量或者函数的声明前,用来说明"此变量/函数是在别处定义的,要在此处引用".1. extern修饰变量的声明. 如果文件a.c需要引用b.c中变量 ...
- Angular 1.x 升级到 Angular 2
原项目用ng1.5写的,现在改成ng2.0了,踩了不少坑,不过都忘记了. 如果你也正好要做这个工作,正好看到这个文章,不妨参考下. AngularJs 1.x -> 2.0 ng-repeat ...
- radio相关
radio 按钮组, name=”sex”. <input type="radio" name="sex" value="Male"& ...
- 通过html和css做出下拉导航栏的效果
通过观察了百度的首页,对于更多产品一栏,觉得可以不涉及JS便可写出下拉导航栏的效果 1.先设计出大体的框架 <div class="nav"> <ul> & ...
- ASP.NET Core 十种方式扩展你的 Views
原文地址:http://asp.net-hacker.rocks/2016/02/18/extending-razor-views.html 作者:Jürgen Gutsch 翻译:杨晓东(Savor ...