Java 线程与并发研究系列二(实现Callable接口)

通过实现Callable和Runnable接口都能够创建线程的执行体,但是Runnable接口并不返回任何值,如果你希望任务在完成的时候能够返回一个值

那么就可以通过实现Callable接口来实现。在JavaAPI中是这样描述Callable接口的:Callable和Runnable相似,他们的类实例都能够被其他Thread

执行,但是Callable接口能够返回一个值或者抛出一个异常,Runnable却不能,实现Callable接口需要重写其唯一的call()方法。

Callable接口是java 5新增加的接口,java5定义了Callable接口中的call()方法的返回类型为Future接口类型,并且java5为Future接口提供一个实现

类FutureTask,FutureTask 还实现了Runnable接口,由于Thread的执行体只接受Runnable接口实例,所以如果想Callable实例作为Thread的执行

体就必须通过FureTask来作为桥梁,即:正常情况下我们是将一个Runable接口实例设置进去(在这里这个实例即是FutureTask对象,因为

FutureTask实现了Runable接口,FutureTask对象即是Runnable接口的一个实例,而Callable接口实例的类型是Future类型,而FutureTask实现了

Future接口,所以Callable接口实例即相当于FutureTask实例:ps:其实不是,但是可以这样理解),下面看Callable接口实例作为Thread的执行体

的实现。

public class MyThread implements Callable<String>{

	@Override
	public String call() throws Exception {
		String str = "史蒂芬森电话";
		System.out.println(str);
		return str;
	}
	
	public static void main(String[] args) {
		MyThread callable = new MyThread();//创建Callable接口实例
		
		FutureTask<String> futureTask = new FutureTask<>(callable);
		
		new Thread(futureTask).start();
		
		//其实就三步:1 创建Callable实例  
		//2将Callable实例设置进FutureTask实例中 
		//3将FutureTask实例作为Runnable类型设置进Thread中
		try {
			System.out.println("子线程的返回结果:"+futureTask.get());
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}
	}
}

运行结果:

下面还介绍一种不通过FutureTask,来实现Callable实例作为线程的执行体

public class MyThread implements Callable<String>{
	int num;
	public MyThread(int num){
		this.num = num;
	}
	@Override
	public String call() throws Exception {
		System.out.println(num);
		return "this task num is "+num;
	}
	
	public static void main(String[] args) {
				
		ExecutorService exec = Executors.newCachedThreadPool();
		List<Future<String>> list = new ArrayList<Future<String>>();
		
		for (int i = 0; i < 10; i++) {
			MyThread callable = new MyThread(i);//创建Callable接口实例
			
			list.add(exec.submit(callable));//将callable接口实例提交进线程池			
		}
		
		for (Future<String>fs:list) {
			try {
				System.out.println(fs.get());
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (ExecutionException e) {
				e.printStackTrace();
			}
		}
		exec.shutdown();
	}
}

执行结果:

在这里还要注意一下,如果你将 exec.shutdown()注释掉,所有线程执行完毕,但是主线程还还没结束,这是因为线程池还没有关闭,导致主线程

无法结束,如果不注释掉,所有的线程执行完毕后,主线程也就自然结束了。

在上面的代码里我们会看到submit()方法会产生一个Future对象,你可以使用isDone方法来检查Future是否完成,当任务完成时,它会返回一个结果

你可以调用get()方法来获取该结果,如果任务还未完成就调用get()方法时,get()方法将阻塞,直至任务完成。

参考链接:http://www.cnblogs.com/liubingna/p/3401403.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值