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);
            }

        }
    }

}
时间: 2024-08-03 16:16:49

java多线程批量执行的时限问题的相关文章

java多线程批量读取文件(七)

新公司入职一个多月了,至今没有事情可以做,十来个新同事都一样抓狂,所以大家都自己学习一些新东西,我最近在看zookeeper,感觉蛮不错的,和微服务的zuul以及eureka功能类似,只是代码复杂了一些.而今天,我所要说的是java多线程读取文件的两个例子: 例子1:java多线程批量读取文件 package face.thread.ReadFile; /** * 多线程读.写文件 *  */import java.io.BufferedReader;import java.io.Buffere

使用JVMTI获取Java多线程程序指令执行次序

使用JVMTI获取Java多线程程序指令执行次序 在Java多线程程序中,由于线程调度,指令间的次序在每次运行时都可能不相同,有时候,我们需要得到指令次序,用来分析程序的行为.这样细粒度的底层行为用一般方法很难完成,我们需要借助 JVM Tool Interface,即JVMTI,来帮助我们获取Java虚拟机执行时的信息.本文先介绍编写JVMTI程序的基本框架,然后介绍如何使用JVMTI来获取多线程程序中指令之间的次序. JVMTI简介 JVMTI是用于编写开发与监视工具的编程接口,使用它可以检

多线程批量执行等待全部结果

来自:http://blog.csdn.net/wxwzy738/article/details/8497853 http://blog.csdn.net/cutesource/article/details/6061229 import java.util.Random; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Callable; import java.util.concurrent.Com

关于java多线程任务执行时共享资源加锁的方式思考

1.加锁方式: 1-1.使用synchronized关键字进行方法或代码块的加锁方式 1-2.使用ReentrantLock类提供的lock()方法的方式 2.代码实现(传统的银行取款存款问题): 2-1.Account.java类:账户类 package com.java.thread; import java.util.concurrent.locks.ReentrantLock; /** * 账户类 * @author steven * */ public class Account {

Java 多线程 锁 存款 取款

http://jameswxx.iteye.com/blog/806968 最近想将java基础的一些东西都整理整理,写下来,这是对知识的总结,也是一种乐趣.已经拟好了提纲,大概分为这几个主题: java线程安全,java垃圾收集,java并发包详细介绍,java profile和jvm性能调优 .慢慢写吧.本人jameswxx原创文章,转载请注明出处,我费了很多心血,多谢 了.关于java线程安全,网上有很多资料,我只想从自己的角度总结对这方面的考虑,有时候写东西是很痛苦的,知道一些东西,但想

Java多线程编程(基础篇)

一.进程和线程的区别: 进程:当前计算机正在运行的程序,进程是cpu分配资源的基本单位,一个进程至少有一个线程. 线程: 计算机中任务调度和最小的执行单元,一个线程也被称为轻量级进程. Java多线程:在单个程序运作的过程中同时运作多个线程,完成不同的工作,称为多线程. 引入线程的好处:Java虚拟机允许应用程序并发的运行多个线程,引入线程可以减少程序并发时的cpu的开销. 二.Java的运行状态图: 初始状态(被创建):创建一个Thread对象,但还未调用start()启动线程时,线程处于初始

Java多线程--让主线程等待所有子线程执行完毕

数据量很大百万条记录,因此考虑到要用多线程并发执行,在写的过程中又遇到问题,我想统计所有子进程执行完毕总共的耗时,在第一个子进程创建前记录当前时间用System.currentTimeMillis()在最后一个子进程结束后记录当前时间,两次一减得到的时间差即为总共的用时,代码如下 Java代码   long tStart = System.currentTimeMillis(); System.out.println(Thread.currentThread().getName() + "开始&

java多线程执行问题

class Demo extends Thread{ public Demo(String name){ super(name); } public void run(){ for(int i=0; i<6; ++i){ System.out.println("i = " + i + "......Thread=" + Thread.currentThread().getName()); try{ Thread.sleep(100); }catch(Inter

Java多线程之后台线程不执行finally

后台线程不执行finally package wzh.daemon; import java.util.concurrent.TimeUnit; class ADaemon implements Runnable { @Override public void run() { try { System.out.println("Starting ADaemon"); TimeUnit.SECONDS.sleep(1); } catch (Exception e) { System.ou