java多线程批量执行的时限问题

需求:需要并发执行三个线程,要求在指定的时间内返回结果,如果某个线程超时,则返回为空。

思路:使用ExecutorService的invokeAll(time,timeUint)方法来设置执行时限,该方法返回一个List<Future<T>>,一旦返回后,即取消尚未完成的任务,然后再从list中读取future并调用future.get()方法来获取线程返回的结果,如果future.get()抛出CancellationException 则说明该任务未完成被取消了。

<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                              long timeout,
                              TimeUnit unit)
                          throws InterruptedException执行给定的任务,当所有任务完成或超时期满时(无论哪个首先发生),返回保持任务状态和结果的 Future 列表。返回列表的所有元素的 Future.isDone() 为 true。一旦返回后,即取消尚未完成的任务。注意,可以正常地或通过抛出异常来终止已完成 任务。如果此操作正在进行时修改了给定的 collection,则此方法的结果是不确定的。 

参数:
tasks - 任务 collection
timeout - 最长等待时间
unit - timeout 参数的时间单位 
返回:
表示任务的 Future 列表,列表顺序与给定任务列表的迭代器所生成的顺序相同。如果操作未超时,则已完成所有任务。如果确实超时了,则某些任务尚未完成。 
抛出: 
InterruptedException - 如果等待时发生中断,在这种情况下取消尚未完成的任务 
NullPointerException - 如果任务或其任意元素或 unit 为 null 
RejectedExecutionException - 如果所有任务都无法安排执行

 

public class CallableAndFutureTask {

    /**
     * @param args
     */
    public static class MyCallable implements Callable<String>{
        
        private String name;
        private int age;
        
        public MyCallable(String name, int age) {
            // TODO Auto-generated constructor stub
            this.name = name;
            this.age = age;
        }

        @Override
        public String call() throws Exception {
            // TODO Auto-generated method stub
            Thread.sleep(new Random().nextInt(4000));
            return "name:"+this.name+" "+"age:"+this.age;
        }
        
    }
    
    public static void main(String[] args) {
        //callable 执行任务,future得到任务执行结果
        ExecutorService threadPool =  Executors.newFixedThreadPool(3);

        int i = 10;
        while(i-- > 0){
        //创建一个tasks的list
            List<MyCallable> tasks = new ArrayList<MyCallable>();
            tasks.add(new MyCallable("tom", 20));
            tasks.add(new MyCallable("john", 30));
            tasks.add(new MyCallable("jack", 40));
       //用来接收任务执行结果 List
<Future<String>> taskResult = null; List<String> result = new ArrayList<String>(); System.out.println("等待结果:"+i); Long s = System.currentTimeMillis(); try { taskResult = threadPool.invokeAll(tasks, 3000, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } for(int j = 0; j < 3; j ++){ try { result.add(taskResult.get(j).get()); } catch (CancellationException e) { // TODO Auto-generated catch block // e.printStackTrace(); System.out.println(j+"cancled"); }catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println("执行时间:"+(System.currentTimeMillis()-s)/1000); if(result.size() == 0){ System.out.println("get no data"); }else{ System.out.println(result); } } } }

和简单的future callable比较,ExecutorService 的submit方法中不能设置时限,只能使用future.get(time,timeUint),但这样一来,再接收结果时就变成了串行,即接收每个任务的结果都需要time的时间,三个任务的执行就变成了3*time,对于单个任务设置超时可以使用这种方式

package com.newTechnologyInJava5;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
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;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;



public class CallableAndFutureTask {

    /**
     * @param args
     */
    public static class MyCallable implements Callable<String>{
        
        private String name;
        private int age;
        
        public MyCallable(String name, int age) {
            // TODO Auto-generated constructor stub
            this.name = name;
            this.age = age;
        }

        @Override
        public String call() throws Exception {
            // TODO Auto-generated method stub
            Thread.sleep(new Random().nextInt(4000));
            return "name:"+this.name+" "+"age:"+this.age;
        }
        
    }
    
    public static void main(String[] args) {
        //callable 执行任务,future得到任务执行结果
        ExecutorService threadPool =  Executors.newFixedThreadPool(3);

        int i = 10;
        while(i-- > 0){

            Future<String> future1 = threadPool.submit(new MyCallable("tom", 20));
            Future<String> future2 = threadPool.submit(new MyCallable("john", 30));
            Future<String> future3 = threadPool.submit(new MyCallable("jack", 40));
            try {
                
                try {
                    result.add(future1.get(3000, TimeUnit.MILLISECONDS));
                    
                } catch (TimeoutException e) {
                    // TODO Auto-generated catch block

                    future1.cancel(true);
                }
                try {
                    result.add(future2.get(3000, TimeUnit.MILLISECONDS));
                    
                } catch (TimeoutException e) {
                    // TODO Auto-generated catch block

                    future2.cancel(true);
                }
                try {
                    result.add(future3.get(3000, TimeUnit.MILLISECONDS));
                    
                } catch (TimeoutException e) {
                    // TODO Auto-generated catch block

                    future3.cancel(true);
                }
                
    
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ExecutionException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            if(result.size() == 0){
                System.out.println("get no data");
            }else{
                System.out.println(result);
            }
            
        }
    }

}

 

转载于:https://www.cnblogs.com/vitosun/p/5377307.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值