簡體   English   中英

java ExecutorService如何處理超時

[英]java ExecutorService how to handle timeouts

我試圖創建一個存根以同時調用多個Web服務,但是在處理CancellationException時出現錯誤。 這是主要方法

    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已完成。 我想做的是,在超時周期結束時,如果到那時還沒有完成任何線程,我想取消這些線程並設置錯誤狀態,但不要一直拋出異常。 我該如何實現?

另外,我想顯示所有已執行的線程和未執行的線程的結果。

由於某些原因,答案將被刪除。 請把它們放在那兒,這可能會幫助其他沒有確切尋找此東西的人。

我終於弄清楚了如何檢查線程是否完成以及如何處理取消的線程。 下面是代碼。

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

我使用Future方法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;
}
}

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM