文档章节

java 并发 - 带返回结果的任务

pan_1308
 pan_1308
发布于 2017/08/24 10:04
字数 1152
阅读 12
收藏 2

一、概述

1、JDK5提供了有可返回值的任务的执行。java.util.concurrent 中 Callable 与 Futrue 用以实现带返回值的任务执行。

2、 Callable:此接口有一个call()方法。在这个方法中,你必须实现任务的(处理)逻辑。Callable接口是一个参数化的接口。意味着你必须表明 call() 方法返回的数据类型。

      Future:此接口有一些方法来保证 Callable 对象结果的获取和管理它的状态。

3、使用 Callable 与 Futrue 与使用 Runnable 最大的两个区别在于:

      》Callable/Future是带返回值的;Runnable无法带返回值。

      》Callable/Future所执行的任务是可取消的。Runnable的任务无法取消。

      其关系如下所示:

二、详解

Callable接口

1、Callable 接口类似于 Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。可返回值的任务必须实现 Callable 接口。

2、V call() throws Exception 方法用于计算结果,如果无法计算结果,则抛出一个异常。V是call方法的结果类型。

3、Callable接口定义了一个call方法可以作为线程的执行体,但 call 方法比 run 方法更强大:

    call()方法可以有返回值。

    call()方法可以申明抛出异常。

4、通过 ExecutorSevice 的submit()方法将Callable提交至线程池中执行,submit()方法返回一个Future实例。

5、使用 CompletionService 接口可以用于提交一组Callable任务,其take()方法返回已完成的一个Callable任务对应的Future实例。好比同时种了几块地的麦子,然后就等待收割。收割时,则是那块先成熟了,则先去收割哪块麦子。

Futrue接口

Future 表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。如果为了可取消性而使用 Future 但又不提供可用的结果,则可以声明 Future<?> 形式类型、并返回 null 作为底层任务的结果。一旦计算完成,就不能再取消计算。

1、提交(submit()方法)Callable任务,可以获取一个Future实例。Futrue实例调用get()方法即可获取Callable任务返回值。

2、V get():返回Callable任务里的call()方法的返回值,调用该方法将导致线程阻塞,必须等到子线程结束才得到返回值。

三、案例-代码实现

import java.util.concurrent.Callable;

public class FactorialCalculator implements Callable<Integer>{

	private Integer number;
	
	public FactorialCalculator(Integer number) {
		this.number = number;
	}
    
	public Integer call() throws Exception {
	    int result = 1;
	    if(number != 0 && number != 1){
	    	for(int i=1;i<=number;i++){
	    		result *= i;
	    		Thread.sleep(500);
	    	}
	    }
	    return result;
	}
}
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;

public class FactorialCalculatorTest {

	public static void main(String[] args) {
		ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(2);
		List<Future<Integer>> resultList = new ArrayList<Future<Integer>>();
        for(int i=0;i<3;i++){
        	int random = new Random().nextInt(5);
        	FactorialCalculator calculator = new FactorialCalculator(random);
        	//调用执行者的submit()方法来提交FactorialCalculator任务给执行者。
        	//这个方法返回Future<Integer>对象来管理任务,并且最终获取它的结果。
        	Future<Integer> future = executor.submit(calculator);
        	resultList.add(future);
        }
        
        do {
		  System.out.println("Main:已完成的任务数量:" + executor.getCompletedTaskCount());
		  for (int i=0; i<resultList.size(); i++) {
			  Future<Integer> result = resultList.get(i);
			  System.out.println("Main: 任务staus:"+ result.isDone()+",i=" +i); // 遍历,输入 result 任务是否已完成.
		  }
		  try {
			Thread.sleep(500);
		  } catch (InterruptedException e) {
			e.printStackTrace();
		  }
		} while (executor.getCompletedTaskCount() < resultList.size()); //如果执行者中的已完成任务数小于10,重复这个循环。
        
        System.out.println("Main: Results:");
        for (int i=0; i<resultList.size(); i++) {
			  Future<Integer> result = resultList.get(i);
			  Integer num = null;
			  try {
				num = result.get();
			  } catch (InterruptedException e) {
					e.printStackTrace();
			  } catch (ExecutionException e) {
					e.printStackTrace();
			  }
			  System.out.println("Main: 任务 结果:"+ num+",i=" +i); // 遍历,输入 result 结果
		}
        executor.shutdown();
	}
}
//console结果:
Main:已完成的任务数量:0
Main: 任务staus:false,i=0
Main: 任务staus:false,i=1
Main: 任务staus:false,i=2
Main:已完成的任务数量:0
Main: 任务staus:false,i=0
Main: 任务staus:false,i=1
Main: 任务staus:false,i=2
Main:已完成的任务数量:0
Main: 任务staus:false,i=0
Main: 任务staus:false,i=1
Main: 任务staus:false,i=2
Main:已完成的任务数量:1
Main: 任务staus:true,i=0
Main: 任务staus:false,i=1
Main: 任务staus:false,i=2
Main:已完成的任务数量:2
Main: 任务staus:true,i=0
Main: 任务staus:true,i=1
Main: 任务staus:false,i=2
Main:已完成的任务数量:2
Main: 任务staus:true,i=0
Main: 任务staus:true,i=1
Main: 任务staus:false,i=2
Main:已完成的任务数量:2
Main: 任务staus:true,i=0
Main: 任务staus:true,i=1
Main: 任务staus:false,i=2
Main: Results:
Main: 任务 结果:6,i=0
Main: 任务 结果:24,i=1
Main: 任务 结果:24,i=2

 

© 著作权归作者所有

pan_1308
粉丝 5
博文 95
码字总数 58819
作品 0
黄冈
私信 提问
读书笔记之《Java并发编程的艺术》-并发编程容器和框架(重要)

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
661
1
【死磕Java并发】—– 死磕 Java 并发精品合集

【死磕 Java 并发】系列是 LZ 在 2017 年写的第一个死磕系列,一直没有做一个合集,这篇博客则是将整个系列做一个概览。 先来一个总览图: 【高清图,请关注“Java技术驿站”公众号,回复:脑...

chenssy
2018/07/22
0
0
Java 并发:Executors 和线程池

本文译自:Java Concurrency – Part 7 : Executors and thread pools 让我们开始来从入门了解一下 Java 的并发编程。 本文主要介绍如何开始创建线程以及管理线程池,在 Java 语言中,一个最...

红薯
2010/09/15
34K
18
Active Object 并发模式在 Java 中的应用

本文主要从以下两个方面进行阐述: 使用 C++ 语言,来描述 Active Object 设计模式。 Java 类库对于这样一个典型的模式做了很好的类库层面的封装,因此对于 Java 的开发者来说,很多关于该设计...

红薯
2010/08/08
320
0
在Java中使用协程(Coroutine)

转自:http://bluedavy.com/?p=4 在讲到具体内容之前,不能不先讲下Coroutine的一些背景知识,来先具体了解下什么是Coroutine。 1. 背景知识 现在的操作系统都是支持多任务的,多任务可通过多...

红薯
2010/05/02
1K
2

没有更多内容

加载失败,请刷新页面

加载更多

mysql概览

学习知识,首先要有一个总体的认识。以下为mysql概览 1-架构图 2-Detail csdn |简书 | 头条 | SegmentFault 思否 | 掘金 | 开源中国 |

程序员深夜写bug
今天
8
0
golang微服务框架go-micro 入门笔记2.2 micro工具之微应用利器micro web

micro web micro 功能非常强大,本文将详细阐述micro web 命令行的功能 阅读本文前你可能需要进行如下知识储备 golang分布式微服务框架go-micro 入门笔记1:搭建go-micro环境, golang微服务框架...

非正式解决方案
今天
6
0
前端——使用base64编码在页面嵌入图片

因为页面中插入一个图片都要写明图片的路径——相对路径或者绝对路径。而除了具体的网站图片的图片地址,如果是在自己电脑文件夹里的图片,当我们的HTML文件在别人电脑上打开的时候图片则由于...

被毒打的程序猿
今天
8
0
Flutter 系列之Dart语言概述

Dart语言与其他语言究竟有什么不同呢?在已有的编程语言经验的基础上,我们该如何快速上手呢?本篇文章从编程语言中最重要的组成部分,也就是基础语法与类型变量出发,一起来学习Dart吧 一、...

過愙
今天
5
0
rime设置为默认简体

转载 https://github.com/ModerRAS/ModerRAS.github.io/blob/master/_posts/2018-11-07-rime%E8%AE%BE%E7%BD%AE%E4%B8%BA%E9%BB%98%E8%AE%A4%E7%AE%80%E4%BD%93.md 写在开始 我的Arch Linux上......

zhenruyan
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部