【转载】Callable、FutureTask中阻塞超时返回的坑点

本文转载自:http://www.cnblogs.com/starcrm/p/5010863.html

案例1:

package com.net.thread.future;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
 
/**
 * @author 
 * @Time:2017年8月18日 上午10:49:07
 * @version 1.0
 * @description
 */ 
  import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.FutureTask;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
  
 public class FutureTaskExample {
  
     public static void main(String[] args) {
         MyCallable callable1 = new MyCallable(1000);
         MyCallable callable2 = new MyCallable(5000);
  
         FutureTask<String> futureTask1 = new FutureTask<String>(callable1);
         FutureTask<String> futureTask2 = new FutureTask<String>(callable2);
  
         ExecutorService executor = Executors.newFixedThreadPool(2);
         executor.execute(futureTask1);
         executor.execute(futureTask2);
          
         while (true) 
         {
             try {
                 if(futureTask1.isDone() && futureTask2.isDone()){
                     System.out.println("Done");
                     //shut down executor service
                     executor.shutdown();
                     return;
                 }
                  
                 if(!futureTask1.isDone()){
                 //阻塞futureTask1
                 System.out.println("FutureTask1 output="+futureTask1.get());
                 }
                 
                 if(!futureTask2.isDone()){
                 //阻塞futureTask2
                 System.out.println("FutureTask2 output="+futureTask2.get(1000,TimeUnit.MILLISECONDS));
                 }

             } catch (InterruptedException | ExecutionException e) {
                 e.printStackTrace();
             }catch(Exception e){
                 //do nothing
             }
         }
          
     }
     
     static class MyCallable implements Callable<String> {
      
         private long waitTime;
          
         public MyCallable(int timeInMillis){
             this.waitTime=timeInMillis;
         }
         @Override
         public String call() throws Exception {
             Thread.sleep(waitTime);
             return Thread.currentThread().getName();
         }
      
     }
 }

运行结果很简单,必须是:

FutureTask1 output=pool-1-thread-1
FutureTask2 output=pool-1-thread-2
Done

案例2:

package com.net.thread.future;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
 
/**
 * @author 
 * @Time:2017年8月18日 上午10:49:07
 * @version 1.0
 * @description
 */
public class FutureTaskExample2 {
 
    public static void main(String[] args) {
        MyCallable callable1 = new MyCallable(1000);
        MyCallable callable2 = new MyCallable(5000);
 
        FutureTask<String> futureTask1 = new FutureTask<String>(callable1);
        FutureTask<String> futureTask2 = new FutureTask<String>(callable2);
 
        ExecutorService executor = Executors.newFixedThreadPool(2);
        executor.execute(futureTask1);
        executor.execute(futureTask2);
         
        while (true) 
        {
             try {
                 if(futureTask1.isDone() && futureTask2.isDone()){
                     System.out.println("Done");
                     //shut down executor service
                     executor.shutdown();
                     return;
                 }
                  
                 if(!futureTask1.isDone()){
                 //阻塞futureTask1
                 System.out.println("FutureTask1 output="+futureTask1.get());
                 }
                  
                 System.out.println("Waiting for FutureTask2 to complete");
                 String s = futureTask2.get(1000, TimeUnit.MILLISECONDS); //阻塞500毫秒
                 if(s !=null){
                     System.out.println("FutureTask2 output="+s);
                 }
                 else{
                     System.out.println("FutureTask2 output is null");
                 }
             } catch (InterruptedException | ExecutionException e) {
                 e.printStackTrace();
             }catch(Exception e){
                 //do nothing
             }  
        }
    }
    
    
    static class MyCallable implements Callable<String> {
     
        private long waitTime;
         
        public MyCallable(int timeInMillis){
            this.waitTime=timeInMillis;
        }
        @Override
        public String call() throws Exception {
            Thread.sleep(waitTime);
            return Thread.currentThread().getName();
        }
     
    }
 
}

运行结果:

FutureTask1 output=pool-1-thread-1
Waiting for FutureTask2 to complete
Waiting for FutureTask2 to complete
Waiting for FutureTask2 to complete
Waiting for FutureTask2 to complete
FutureTask2 output=pool-1-thread-2
Done

说明:

1、get()方法用来获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回;

2、get(long timeout, TimeUnit unit)用来获取执行结果,如果超过指定时间,直接结束执行下面的代码;如果是在循环中,则跳出本次循环进行下一次轮训(continue功能类似)。

原文地址:https://www.cnblogs.com/chen1-kerr/p/7388725.html