java核心知识点学习----创建线程的第三种方式Callable和Future CompletionService
前面已经指出通过实现Runnable时,Thread类的作用就是将run()方法包装成线程执行体,那么是否可以直接把任意方法都包装成线程执行体呢?Java目前不行,但其模仿者C#中是可以的.
Callabel接口可以看成是Runnable接口的增强版,只不过其线程执行体call()方法比run方法更加强大罢了:
>>call()方法中可以有返回值
>>call()方法中可以声明抛出异常.
一.创建线程的第三种方式----使用Callable对象进行创建
package com.amos.concurrent;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* @ClassName: CallableAndFuture
* @Description: 多线程中的Callable和Future学习
* @author: amosli
* @email:hi_amos@outlook.com
* @date Apr 22, 2014 12:07:26 AM
*/
public class CallableAndFuture {
public static void main(String[] args) throws Exception, ExecutionException {
ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();
Future<String> future = newSingleThreadExecutor.submit(new Callable<String>() {
public String call() throws Exception {
Thread.sleep(20);
return "hi,amos";
}
});
// System.out.println("future:"+future.get(1,TimeUnit.MILLISECONDS));//等待指定的时间
System.out.println("future:" + future.get());
}
}
效果如下:

注:
1.这里要注意的是,创建线程时执行任务不是用execute()方法去执行了,而是用submit()方法.
2.同时要注意,这里call()方法返回值,要和上面的保持一致.
3.另外,可以设置最大等待时间,就是等待程序的返回值,这里使用get()方法.
4.其常用的其它方法有cancel(),isCancelled(),isDone(),分别表示取消关联的任务,是否已经取消,任务是否已经完成.
二.CompeltionService
CompeltionService主要用于提交一组Callable对象,其take方法用于返回已完成的callable任务的Future对象.可以用麦子收割来作比喻,种了10亩地的麦子,哪一块先成熟先收割哪一块.
举例:
package com.amos.concurrent; import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CallableAndFuture { public static void main(String[] args) throws Exception, ExecutionException {
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(10);
CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(newFixedThreadPool);
for(int i=0;i<11;i++){//创建10个任务
final int task=i;
completionService.submit(new Callable<Integer>() {//提交任务
public Integer call() throws Exception {
Thread.sleep(new Random().nextInt(3000));//最多3秒
return task;
}
});
}
//take
for(int i=0;i<11;i++){
System.out.println("已完成的任务:"+completionService.take().get());
}
}
效果如下图所示:

注:由结果也可以看出来,其随机结果是根据任务的先后完成顺序来的,使用其take()方法可以获取其返回结果.
java核心知识点学习----创建线程的第三种方式Callable和Future CompletionService的更多相关文章
- java核心知识点----创建线程的第三种方式 Callable 和 Future CompletionService
前面已经指出通过实现Runnable时,Thread类的作用就是将run()方法包装成线程执行体,那么是否可以直接把任意方法都包装成线程执行体呢?Java目前不行,但其模仿者C#中是可以的. Call ...
- Java反射机制(创建Class对象的三种方式)
1:了解什么是反射机制? 在通常情况下,如果有一个类,可以通过类创建对象:但是反射就是要求通过一个对象找到一个类的名称: 2:在反射操作中,握住一个核心概念: 一切操作都将使用Object完成,类 ...
- 创建线程的第三种方式——使用Callable接口
Callable是类似于Runnable的接口,实现Callable的类和实现Runnable的类都是可被其他线程执行的任务. 优点:有返回值 缺点:实现繁琐 简单实现: CallableAndFut ...
- Java核心知识点学习----线程中如何创建锁和使用锁 Lock,设计一个缓存系统
理论知识很枯燥,但这些都是基本功,学完可能会忘,但等用的时候,会发觉之前的学习是非常有意义的,学习线程就是这样子的. 1.如何创建锁? Lock lock = new ReentrantLock(); ...
- java核心知识点学习----并发和并行的区别,进程和线程的区别,如何创建线程和线程的四种状态,什么是线程计时器
多线程并发就像是内功,框架都像是外功,内功不足,外功也难得精要. 1.进程和线程的区别 一个程序至少有一个进程,一个进程至少有一个线程. 用工厂来比喻就是,一个工厂可以生产不同种类的产品,操作系统就是 ...
- Java核心知识点学习----使用Condition控制线程通信
一.需求 实现线程间的通信,主线程循环3次后,子线程2循环2次,子线程3循环3次,然后主线程接着循环3次,如此循环3次. 即:A->B->C---A->B->C---A-> ...
- Java核心知识点学习----多线程中的阻塞队列,ArrayBlockingQueue介绍
1.什么是阻塞队列? 所谓队列,遵循的是先进先出原则(FIFO),阻塞队列,即是数据共享时,A在写数据时,B想读同一数据,那么就将发生阻塞了. 看一下线程的四种状态,首先是新创建一个线程,然后,通过s ...
- java 中创建线程有哪几种方式?
Java中创建线程主要有三种方式: 一.继承Thread类创建线程类 (1)定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务.因此把run()方法称为执行 ...
- Java反射机制(创建Class对象的三种方式)
1:SUN提供的反射机制的类: java.lang.Class<T> java.lang.reflect.Constructor<T> java.lang.reflect.Fi ...
随机推荐
- 【C】 02 - 程序结构和预处理
在正式进入C的语法之前,有必要对其整体外观和组成元素作一个浏览.这部分内容对大多数人是比较陌生的,但它们却是C的起点和骨架.而这些内容涉及的背景或细节又可以展开为专门的课题,这里也只是浅尝则止,说明个 ...
- intelij idea 2016.2注册码
激活码: 43B4A73YYJ-eyJsaWNlbnNlSWQiOiI0M0I0QTczWVlKIiwibGljZW5zZWVOYW1lIjoibGFuIHl1IiwiYXNzaWduZWVOYW1l ...
- Oracle导入和导出
导出:EXP userid=<username>/<password>@<service_name> file=<dmpname> e.g.exp sa ...
- 不是技术牛人,如何拿到国内IT巨头的Offer(转载)
转载的文章,中间有几段需要去学习. byvoid 面阿里星计划的面试结果截图泄漏,引起无数IT屌丝的羡慕敬仰.看看这些牛人,NOI金牌,开源社区名人,三年级开始写Basic-在跪拜之余我们不禁要想,和 ...
- yum 部署nginx
第一步,在/etc/yum.repos.d/目录下创建一个源配置文件nginx.repo: cd /etc/yum.repos.d/ vim nginx.repo 填写如下内容: [nginx ...
- 安卓:assets目录下的文本文件(不受R文件节制)
try { InputStream in = getAssets().open("testAsset.txt"); byte[] buffer = new byte[1024]; ...
- R型思维模式对软件开发的影响(草稿)
The pragmatic programmers 一直在工作之余读些书,之前主要是纯英文版的计算机相关的算法,编译器,数学等,想通过读这些书来提高自己每日工作效能,结果收效甚微.一是,因为纯英文的书 ...
- c#版在pc端发起微信扫码支付
等了好久,微信官方终于发布了.net的demo. 主要代码: /** * 生成直接支付url,支付url有效期为2小时,模式二 * @param productId 商品ID * @return 模式 ...
- auto,register,static分析
1.关键字auto auto是C语言中局部变量的默认类型,指明声明的变量在程序的栈上分配空间. 2.关键字static 指明变量的“静态”属性,局部变量存储在静态存储区: 文件作用标示符,只能在声明的 ...
- php判断 !==false
测试 if($res !== false){ echo "未定义通过<br>"; }else{ echo "未定义不通过<br>"; } ...