jdk1.8的Future特性简介及使用场景

2023-11-05

Future简介

什么是Future?

Future是一个接口,用来返回异步的结果。它表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能使用 get 方法来获取结果,此方法在计算完成前可以被阻塞。

Future的使用场景

Future通常被使用在需要多个线程协作计算的情形中。

Future接口内部的常用方法

   1> cancel,取消Callable的执行,当Callable还没有完成时
   2> get,获得Callable的返回值
   3> isCanceled,判断是否取消了
   4> isDone,判断是否完成

Future的常见用法

一、基础用法:

重写Callable接口的call方法,放到异步线程的.submit方法中执行。

       可以直接重写call方法;
       也可以定义一个类继承Callable接口,在类中重写call方法.

代码实例:
package future.com;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

class TaskWithResult implements Callable<String>{

	public String call() throws Exception {
		// TODO Auto-generated method stub
		Thread.sleep(1000);
		return "OK";
	}
}

public class CallableDemo {
	
	public static void main(String[] args) throws Exception {

		/**
		 * 一、直接重写call方法,然后在.submit方法中传入call
		 * */
		// 开启线程池
		final ExecutorService exec = Executors.newFixedThreadPool(3);
		// 直接重写Callable的call方法
		Callable<String> call = new Callable<String>() {
			public String call() throws Exception {
				return "Other less important but longtime things.";
			}
		};
		Future<String> task = exec.submit(call);
		
		/**
		 * Future线程类的常用方法
		 * */
		// 获取Callable返回值
		System.out.println(task.get());
		// 判断是否执行完成
		System.out.println(task.isDone());
		//当Callable没执行完成时,取消Callable的执行
		System.out.println(task.cancel(false));
		// 判断是否被取消
		System.out.println(task.isCancelled());

		/**
		 * 二、TaskWithResult类继承Callable接口,在类里面重写call方法,.submit方法中传入TaskWithResult类
		 * */
		Future<String> st=exec.submit(new TaskWithResult());
		System.out.println(st.get());
		
		// 关闭线程
		exec.shutdown();
	}
}

二、进阶用法:

定义返回值类型为进程类的方法,异步调用,阻塞等待。再对结果集进行处理

假定一个场景:
要循环调访问某些接口,并处理得到的数据。

具体实现:
1)service层定义一个返回值为进程类的请求方法,在该方法中请求数据并返回结果

package com.service;

package com.service;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.endtity.JsonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.util.concurrent.Future;

@Service
public class JsonService {

    @Autowired
    private RestTemplate restTemplate;
    private ObjectMapper objectMapper = new ObjectMapper();

    @Async
    public Future<JsonResult> query(String url, Object param){
        JsonResult result = null;
        try {
            String json = restTemplate.postForObject(url, param, String.class);
            result = objectMapper.readValue(json, new TypeReference<JsonResult>(){});
        } catch (IOException e) {

        } finally {

        }
        return new AsyncResult<>(result);
    }
}

2)定义返回结果

com.endtity.JsonResult

package com.endtity;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

@Data
public class JsonResult {
    @JsonProperty("code")
    private String code;
    @JsonProperty("msg")
    private String msg;
    @JsonProperty("result")
    private Object result;
}

3)Controll层的实现

1> 异步调用取数据service的方法;
2> 阻塞等待,用isDone方法判断是否执行完成;
3> 合并结果集;
4> 按照自己的需求处理结果集,并返回处理后的结果

package com.api;

package com.api;

import com.endtity.JsonResult;
import com.service.JsonService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

@RestController
@RequestMapping("/rest/api/track")
@CrossOrigin("*")
public class JsonControl {

    private Logger logger = LoggerFactory.getLogger(JsonControl.class);

    @Autowired
    private JsonService jsonservice;

    public static void main(String[] args) {
        SpringApplication.run(JsonControl.class, args);
    }

    @PostMapping("test")
    public List<JsonResult> test(@RequestBody Object json) throws InterruptedException, ExecutionException {

        // 配置要循环访问的接口地址
        List<String> ls = new ArrayList();
        ls.add("https://");
        ls.add("https://");

        List<JsonResult> result = null;
        Map<String, Future<JsonResult>> obj = new HashMap<>();

        // 异步调用
        for(int i=0; i<ls.size(); i++){
            Future<JsonResult> ss=jsonservice.query(ls.get(i), json);
            obj.put(i+"", ss);
        }
        
        // 阻塞等待
        while(true){
            boolean bool=true;
            for(int i=0;i<3;i++){
                if(bool&&obj.get(i+"").isDone()){
                    bool=true;
                }else{
                    bool=false;
                }
            }
            if(bool){
                break;
            }
        }
        
        // 合并结果集
        for(int i=0; i<ls.size(); i++){
            JsonResult o = obj.get(i+"").get();
            result.add(o);
        }

        // 对结果集进行聚合


		// 返回结果集
        return result;
    }
}

一些实现细节:

1)在写service层的进程类方法是,虽然进程执行完后丢给我们的是一个 JsonResult 的结果对象。但是在进程类中不能直接 return 一个 JsonResult 对象,而是应该 new 一个 异步进程结果AsyncResult<>()将方法的执行结果传出。
2)control层有一个 while 死循环,必须通过isDone()方法判断进程全部执行完后才能对结果集进行处理。
3)记得处理一些相关的异常

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

jdk1.8的Future特性简介及使用场景 的相关文章

  • 基于计算机视觉实现自动报靶系统

    基于计算机视觉实现自动报靶系统 自动报靶系统是一种通过计算机视觉技术实现的靶标自动识别和跟踪的系统 该系统可以应用于一些需要高精度打靶的场合 如射击比赛 训练等 本文将介绍如何使用MATLAB实现一个基于计算机视觉的自动报靶系统 准备工作
  • LoadRunner录制图片验证码

    LoadRunner录制图片验证码 LoadRunner自身是无法捕获到图片验证码的 但是我们可以帮助LoadRunner来实现验证码的捕获 1 图片验证码 图片验证码的产生来自服务器端 由服务器生成随机数 然后写入到图片中 虽然LR可以录

随机推荐