1. Runnable接口的限制

JDK提供了ExecutorService接口表示线程池,可以通过submit提交一个任务。

    ExecutorService executor = Executors.newFixedThreadPool(4);
executor.submit(task);

但这里的task有个问题,因为继承制Runnable,如果希望返回一个结果,只能用result来表示,这样主线程获取结果,就很不方便。

class Task implements Runnable{
public String result; //只能将结果保存到result,再去读取
public void run(){
this.result = longTimeCalculation();
}
}

因此JDK又提供了一个Callable接口。

2. Callable接口

相比Runnable接口,Callable接口多了一个返回值。这样我们就可以用submit()方法把一个Callable的task提交给executor,异步执行。

不需要返回结果 需要返回结果
Runnable Callable

当我们使用Callable接口时候,我们需要实现一个泛型接口。例如我们期望返回值是一个String,我们就写implements Callable,并覆写call()方法。
```#java
class Task implements Callable{
public String call() throws Exception{
return longTimeCalculation();
}
}
```
## 3. Future
如果获得异步执行的结果呢?
```#java
Callable task = new Task();
ExecutorService executor = Executors.newFixedThreadPool(4);
Future future = exector.submit(task);
String result = future.get(); //可能阻塞
```
当我们提交一个Callable任务以后,会同时获得一个Future对象。
接着在主线程的某个时刻调用Future对象的get()方法就可以获得异步执行的结果:
* 在调用get()方法的时候,如果异步任务已经完成,就直接获得结果;
* 如果异步任务未完成,那么get()方法就会阻塞,直到任务完成以后,返回结果。

Future接口:表示一个未来可能会返回的结果

    get():返回一个异步执行的结果
get(long timeout, TimeUnit unit):指定一个最长的等待时间
cancel(boolean mayInterruptIfRunning):中断一个异步任务的执行
isDone():判断当前的异步任务是否已经完成

4. 示例

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future; class DownloadTask implements Callable<String> {
String url;
public DownloadTask(String url){
this.url = url;
}
public String call() throws Exception {
System.out.println("start download " + url + "...");
URLConnection conn = new URL(this.url).openConnection();
conn.connect();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))){ String s = null;
StringBuilder sb = new StringBuilder();
while ((s = reader.readLine()) != null) {
sb.append(s).append("\n");
}
return sb.toString();
} } }
public class Main{
public static void main(String[] args) throws Exception{
ExecutorService executor = Executors.newFixedThreadPool(3);
DownloadTask task = new DownloadTask("https://www.sina.com.cn");
Future<String> future = executor.submit(task);
String html = future.get();
System.out.println(html);
executor.shutdown();
}
}

5.总结:

  • 需要返回结果,使用Callable;不需要返回结果,使用Runnable
  • 提交Callable任务,可以获得一个Future对象
  • 可以用Future在将来某个时刻获得结果

最新文章

  1. 操作系统中的P,V操作(转)
  2. Elasticsearch 教程--分布式集群
  3. php 异常处理类
  4. RAD Studio 2009-10Seattle IDE Fix Pack 5.94
  5. JdbcTemplate queryForMap EmptyResultDataAccessException
  6. Codeforces Round #136 (Div. 2)
  7. 01.安装Memcached
  8. OpenJudge 2817:木棒 / Poj 1011 Sticks
  9. python自动开发之第二十一天
  10. Adobe Acrobat XI Pro 两种破解方式 Keygen秘钥 license替换 亲测有效
  11. Markdown简短教程
  12. gmapping 学习
  13. java 数据结构 图
  14. 从零开始理解JAVA事件处理机制(2)
  15. nginx基础
  16. leetcode143. Reorder List
  17. 在虚拟机上运行zookeeper的过程中,xshell连接不上虚拟机
  18. foreach 與 reference 的雷
  19. adb devices 找不到设备的解决方法
  20. Charles 安装图解(Mac 抓包工具)

热门文章

  1. LeetCode 182. Duplicate Emails (查找重复的电子邮箱)
  2. DXP 常用功能
  3. 【转】Java程序CPU飙升问题排查方法
  4. Apache Spark 2.2.0 中文文档 - Spark RDD(Resilient Distributed Datasets)
  5. python日常使用
  6. CTR预估的常用方法
  7. PHP算法之两数之和
  8. eclipse导出说明文档
  9. 实现div里面有placeholder形式
  10. K-Anonymous Sequence