1

我想創建一個存根來同時調用多個Web服務,但是當我處理CancellationException時出現錯誤。這裏的主要方法java ExecutorService如何處理超時

ExecutorService pool= Executors.newFixedThreadPool(7); 
    List<Future<Long>> futureList = new ArrayList<Future<Long>>(); 
    Set<CallableDemo> callList = new HashSet<CallableDemo>(); 

    callList.add(new CallableDemo(0L)); 
    callList.add(new CallableDemo(10L)); 
    callList.add(new CallableDemo(20L)); 
    callList.add(new CallableDemo(30L)); 
    callList.add(new CallableDemo(40L)); 
    callList.add(new CallableDemo(50L)); 
    callList.add(new CallableDemo(-600L)); 
    callList.add(new CallableDemo(-700L)); 
    callList.add(new CallableDemo(-800L)); 
    callList.add(new CallableDemo(-900L)); 

    futureList = pool.invokeAll(callList, 15L, TimeUnit.SECONDS); 

    for(Future<Long> fut : futureList){ 
    try { 
      System.out.println(new Date()+ "::"+fut.get()); 
    } catch (InterruptedException e) { 
     System.out.println("Done :)"); 
     e.printStackTrace(); 
     Thread.currentThread().interrupt(); 
    } 
    catch (ExecutionException e) { 
     System.out.println("Done :)"); 
     e.printStackTrace(); 
     Thread.currentThread().interrupt(); 
    } 
    } 
    executor.shutdown(); 

這裏是CallableDemo,

import java.util.concurrent.Callable; 
public class CallableDemo implements Callable<Long> 
{ 
private Long count = 0L; 

public CallableDemo(Long i) 
{ 
    this.count = i; 
} 

public Long call() throws Exception 
{ 
    Long i; 
    for(i = this.count; i < 100L; i++) 
    { 
     try { Thread.sleep(100); } 
      catch (InterruptedException e) { 
       Thread.currentThread().interrupt(); 
       return i; 
     } 
     System.out.println(Thread.currentThread().getName() + " - " + i); 
    } 
    return i; 
} 
} 

因爲我已經指定15秒的超時時間,這裏是我得到的輸出:

pool-2-thread-1 - -764 
pool-2-thread-6 - -744 
pool-2-thread-2 - 97 
pool-2-thread-4 - -563 
pool-2-thread-1 - -763 
pool-2-thread-6 - -743 
pool-2-thread-5 - -463 
Exception in thread "main" java.util.concurrent.CancellationException 
    at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:220) 
    at java.util.concurrent.FutureTask.get(FutureTask.java:83) 
    at CallableTest.main(CallableTest.java:44) 

正如你所看到的,線程3已經完成。我想要做的是,在超時期結束時,如果任何線程尚未完成,我想取消這些線程併發出錯誤狀態,但不會一直拋出異常。我如何實現這一目標?

此外,我想顯示所有執行的線程和那些沒有執行的線程的結果。

出於某種原因,答案正在被刪除。請讓他們在那裏,這可能會幫助其他人沒有正在尋找這個。

+1

一個CompletionExecutionService可能在那種情況下非常有用。 – assylias 2014-11-06 22:10:38

+0

您是否刪除了答案? – roymustang86 2014-11-06 23:07:09

+0

是的,它沒有回答你的問題。 – assylias 2014-11-07 07:37:46

回答

1

我終於想出瞭如何檢查線程是否完成,以及如何處理取消的線程。以下是代碼。

public class CallableTest 
{ 
public static void main(String args[]) throws Exception 
{ 
    ExecutorService executor = Executors.newFixedThreadPool(10); 
    ExecutorService pool= Executors.newFixedThreadPool(10); 
    List<Future<Long>> futureList = new ArrayList<Future<Long>>(); 
    Set<CallableDemo> callList = new HashSet<CallableDemo>(); 

     //submit Callable tasks to be executed by thread pool 
     //<Long> future = executor.submit(callable); 
     //add Future to the list, we can get return value using Future 
     //list.add(future); 

     callList.add(new CallableDemo(0L)); 
     callList.add(new CallableDemo(10L)); 
     callList.add(new CallableDemo(20L)); 
     callList.add(new CallableDemo(30L)); 
     callList.add(new CallableDemo(40L)); 
     callList.add(new CallableDemo(50L)); 
     callList.add(new CallableDemo(-600L)); 
     callList.add(new CallableDemo(-700L)); 
     callList.add(new CallableDemo(-800L)); 
     callList.add(new CallableDemo(-900L)); 

     futureList = pool.invokeAll(callList, 15L, TimeUnit.SECONDS); 

     for(Future<Long> fut : futureList){ 
       try { 
        //print the return value of Future, notice the output delay in console 
        // because Future.get() waits for task to get completed 
        if(!fut.isCancelled()) 
         System.out.println(new Date()+ "::"+fut.get()); 
       } catch (InterruptedException e) { 
        //e.printStackTrace(); 
        System.out.println("Done :)"); 
        //Thread.currentThread().interrupt(); 
       } 
       catch (ExecutionException e) { 
        //e.printStackTrace(); 
        System.out.println("Done :)"); 
        //Thread.currentThread().interrupt(); 
       } 
      } 
      //shut down the executor service now 
      executor.shutdown(); 
      System.out.println("Done :)"); 
} 
} 

我用的是未來的方法isCancelled(),或者你可以使用isDone()爲好,http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html

public class CallableDemo implements Callable<Long> 
{ 
private Long count = 0L; 

public CallableDemo(Long i) 
{ 
    this.count = i; 
} 

public Long call() throws InterruptedException 
{ 
    Long i; 
    for(i = this.count; i < 100L; i++) 
    { 
     try { Thread.sleep(100); } 
      catch (InterruptedException e) { 
       System.out.println("Interruped " + Thread.currentThread().getName()); 
       //Thread.currentThread().interrupt(); 
      return i; 
     } 
     //System.out.println(Thread.currentThread().getName() + " - " + i); 
    } 
    System.out.println("Finished " + Thread.currentThread().getName()); 
    return i; 
} 
} 
+1

不要使用'isDone()';當invokeAll返回時它總是返回true,但是由於各種原因可以完成任務:完成成功,失敗或取消。你應該接受你的答案。好工作搞清楚。 – erickson 2014-11-07 18:05:39

0

實施ExecutorService的ThreadPools不提供對其工作線程的訪問。因此,請使用自定義ThreadFactory。讓它將線程存儲在集合中,以便稍後可以中斷它們。確保您的作業Runnable具有適當的中斷處理來設置錯誤狀態。提供可以表示錯誤狀態和實際返回值的可調用返回類型。