Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4455786
  • 博文数量: 1214
  • 博客积分: 13195
  • 博客等级: 上将
  • 技术积分: 9105
  • 用 户 组: 普通用户
  • 注册时间: 2007-01-19 14:41
个人简介

C++,python,热爱算法和机器学习

文章分类

全部博文(1214)

文章存档

2021年(13)

2020年(49)

2019年(14)

2018年(27)

2017年(69)

2016年(100)

2015年(106)

2014年(240)

2013年(5)

2012年(193)

2011年(155)

2010年(93)

2009年(62)

2008年(51)

2007年(37)

分类: Java

2018-09-13 12:53:06

https://blog.csdn.net/u010940300/article/details/50251841

上一节中讲到了ExecutorService中有一些管理Thread的方法

execute(Runnable)
submit(Runnable)
submit(Callable)
invokeAny(...)
invokeAll(...)
  • 1
  • 2
  • 3
  • 4
  • 5

execute(Runnable)

这个方法使用的参数是 java.lang.Runnable 包中的对象,调用这个方法之后将会异步执行runnable。

ExecutorService executorService = Executors.newSingleThreadExecutor();

executorService.execute(new Runnable() { public void run() {
        System.out.println("Asynchronous task");
    }
});

executorService.shutdown();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

通过工厂构建一个ExecutorService实例,然后执行 自定义的Runnable,这个方法是没有返回值的,如果你想得到一个返回值,可以使用 Callable对象替代Runnable(后面会讲到)

submit(Runnable)

这个方法同execute(Runnable)一样,都是异步执行一个task,但是submit方法是有返回值的,它返回一个Future 对象,通过这个对象,可以检查这个Runnable实例是否执行完成。

Future future = executorService.submit(new Runnable() { public void run() {
        System.out.println("Asynchronous task");
    }
});

future.get(); //returns null if the task has finished correctly. //这个方法返回的是这个任务结束(不一定正常结束)的结果,必要的时候这个方法会等待结果出来。 //如果返回值为null,则表明这个任务已经正常的执行完毕。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

submit(Callable)

这个方法的参数和submit(Runnable)不同。
Runnable和Callable的区别是,Runnable中onRun()方法是没有返回值的,而Callable中的call()方法是有返回值的。 call()方法的返回值要如何得到呢? 可以通过 submit(Callable)方法的返回值 Future对象得到。
  • 1
  • 2
  • 3
  • 4

举例:

Future future = executorService.submit(new Callable(){ public Object call() throws Exception {
        System.out.println("Asynchronous Callable"); return "Callable Result";
    }
});

System.out.println("future.get() = " + future.get());
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

控制台打印的结果如下:

Asynchronous Callable future.get() = Callable Result
  • 1
  • 2

invokeAny()

这个方法接收的参数是 Callable(或者Callable的实现类)对象的集合

而且这个方法并不会返回 Future对象,而是返回集合中某个Callable对象的return的值,具体是哪一个呢? 答案是:无法确认(这个跟他的机制有关),但是可以确认的是这个Callable对象是完成了的。

机制:如果 集合中的某个task,完成了(或者抛出异常),那么集合中剩余的task将全部会被取消,不会得到执行。

下面是例子:

ExecutorService executorService = Executors.newSingleThreadExecutor(); SetString>> callables = new HashSetString>>();

callables.add(new Callable<String>() { public String call() throws Exception {
        return "Task 1";
    }
});
callables.add(new Callable<String>() { public String call() throws Exception {
        return "Task 2";
    }
});
callables.add(new Callable<String>() { public String call() throws Exception {
        return "Task 3";
    }
}); String result = executorService.invokeAny(callables);

System.out.println("result = " + result);

executorService.shutdown(); 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

这个打印的结果将会是集合中的某一个Callable对象中call()方法返回的值,笔者(不是译者)尝试过多次,打印的结果是不同的, 有时候是 Task 1 
有时候会是 Task 2 等。

invokeAll()

参数:这个方法接收的参数是 Callable(或者Callable的实现类)对象的集合

这个方法将会调用 集合中全部的 Callable对象。

返回值:将返回一个包含Future对象的List集合,你可以通过 list中的future对象来获取,callable的返回值。

需要注意的是task结束的时候可能是因为 异常(没有正常结束),所以这个task可能并没有成功。但是通过future对象是无法判断,task 是否成功执行 结束,还是 异常 结束。

ExecutorService executorService = Executors.newSingleThreadExecutor(); SetString>> callables = new HashSetString>>();

callables.add(new Callable<String>() { public String call() throws Exception {
        return "Task 1";
    }
});
callables.add(new Callable<String>() { public String call() throws Exception {
        return "Task 2";
    }
});
callables.add(new Callable<String>() { public String call() throws Exception {
        return "Task 3";
    }
});

ListString>> futures = executorService.invokeAll(callables); for(Future<String> future : futures){
    System.out.println("future.get = " + future.get());
}

executorService.shutdown();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

ExecutorService Shutdown

当你使用ExecutorService的时候,你应该记得关闭它,这样这些被管理的线程才会停止运行。

举例:如果你的应用通过main()方法启动,并且你的 应用中存在一个 激活的 ExecutorService,那么即使你的main thread(main线程)已经退出了,这个应用依然会在后台运行。 原因: ExecutorService中的活跃线程,防止了jvm关闭ExecutorService。

结论:jvm是可能无法关闭ExecutorService的,如果某些情况下,你不希望ExecutorService在后台不受控制的执行,那你在必要的时候 需要手动调用 ExecutorService中的shutdown方法。

通过调用ExecutorService中的shutdown方法可以终止该ExecutorService中的线程,但是ExecutorService并不会立即关闭,但是ExecutorService已经不会再接收新的task了,等到所有的thread完成各自的task,那么这个ExecutorService就会关闭。并且所有task中的结果 会在shutdown方法执行之前 submit(提交),都是已经执行完成了的。并不会存在没有的执行的task。

结论:手动调用shutdown并不会立即关闭ExecutorService,而是等待ExecutorService中所有的任务完成,并且提交之后,才会关闭的。(所以手动调用shotdown方法,可以不必担心存在剩余任务没有执行的情况)

如果你想立即关闭一个ExecutorService,你可以调用shutdownNow方法来实现。调用这个方法,ExecutorService将会”尝试着“关闭所有正在执行的task,这个关闭的过程会自动跳过那些已经submit的task(节省性能)。但是 对于那些正在 执行的task,并不能保证他们就一定会直接停止执行,或许他们会暂停,或许会执行直到完成,但是ExecutorService会尽力关闭所有正在运行的task。

参考链接:链接1

阅读(635) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~