2009-03-12 36 views
11

Tôi thấy điều này trong các tài liệu java: ScheduledAtFixedRate, nó nóiCách lên lịch lại một tác vụ bằng cách sử dụng ScheduledExecutorService?

Nếu bất kỳ thực hiện các nhiệm vụ gặp một ngoại lệ, sau hành đang bị đàn áp

Tôi không muốn điều này xảy ra trong ứng dụng của tôi. Ngay cả khi tôi thấy một ngoại lệ, tôi vẫn luôn muốn các vụ hành quyết tiếp theo xảy ra và tiếp tục. Làm thế nào tôi có thể nhận được hành vi này từ ScheduledExecutorService.

+1

Tôi thích giải pháp được mô tả trong [CosmoCode viết blog ] (http://www.cosmocode.de/en/blog/schoenborn/2009-12/17-uncaught-exceptions-in-scheduled-tasks) – Chobicus

+0

Giải pháp trong _CosmoCode blog_ ** blocks ** (sử dụng 'tương lai. get(); '), chống lại điểm thực thi không đồng bộ được cung cấp bởi' Executor '. – user454322

Trả lời

7

Surround phương pháp Callable.call hoặc phương pháp với một try/catch Runnable.run ...

ví dụ:

public void run() 
{ 
    try 
    { 
     // ... code 
    } 
    catch(final IOException ex) 
    { 
     // handle it 
    } 
    catch(final RuntimeException ex) 
    { 
     // handle it 
    } 
    catch(final Exception ex) 
    { 
     // handle it 
    } 
    catch(final Error ex) 
    { 
     // handle it 
    } 
    catch(final Throwable ex) 
    { 
     // handle it 
    } 
} 

Lưu ý rằng bắt bất cứ điều gì khác so với những gì trình biên dịch cho bạn biết quá (IOException trong mẫu của tôi) không phải là một ý tưởng tốt, nhưng có một số lần, và điều này nghe giống như một trong số họ, rằng nó có thể làm việc ra nếu bạn xử lý nó đúng cách. Hãy nhớ rằng những thứ như Lỗi rất tệ - máy ảo hết bộ nhớ ... vì vậy hãy cẩn thận cách bạn xử lý chúng (đó là lý do tại sao tôi tách chúng ra thành bộ xử lý riêng của chúng thay vì chỉ bắt được (cuối cùng là Throwable) cũ) và không có gì khác).

+0

Lưu ý rằng nếu bạn không bắt được nhiệm vụ được lập biểu lặp lại và OOME xảy ra, bạn sẽ không bao giờ tìm hiểu về nó (trừ khi có gì đó gọi get() trên ScheduledFuture và logging ExecutionExceotions –

+0

Vậy thì ... đoán bạn phải ... ick :-) Tôi sẽ xác minh và sau đó cập nhật câu trả lời của tôi - thx – TofuBeer

+0

Dừng việc thực hiện tiếp theo vì chủ đề cụ thể chấm dứt? Nếu kích thước nhóm chủ đề lớn hơn 1, phần lớn là đúng, thì tại sao việc triển khai ScheduledExecutorService không thể chạy thử bằng cách sử dụng một chuỗi khác? – RRM

1

Tôi gặp vấn đề tương tự. Tôi cũng đã cố gắng thử khối trong phương thức run() nhưng nó không hoạt động.

Vì vậy, tôi đã làm một cái gì đó đang làm việc cho đến nay:

import java.util.concurrent.BlockingQueue; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.LinkedBlockingQueue; 

public class Test2 { 

    static final ExecutorService pool = Executors.newFixedThreadPool(3); 

    static final R1 r1 = new R1(); 
    static final R2 r2 = new R2(); 

    static final BlockingQueue deadRunnablesQueue = new LinkedBlockingQueue<IdentifiableRunnable>(); 

    static final Runnable supervisor = new Supervisor(pool, deadRunnablesQueue); 

    public static void main(String[] args) { 
     pool.submit(r1); 
     pool.submit(r2); 
     new Thread(supervisor).start(); 
    } 

    static void reSubmit(IdentifiableRunnable r) { 
     System.out.println("given to an error, runnable [" + r.getId() 
       + "] will be resubmited"); 
     deadRunnablesQueue.add(r); 
    } 

    static interface IdentifiableRunnable extends Runnable { 
     String getId(); 
    } 

    static class Supervisor implements Runnable { 
     private final ExecutorService pool; 
     private final BlockingQueue<IdentifiableRunnable> deadRunnablesQueue; 

     Supervisor(final ExecutorService pool, 
       final BlockingQueue<IdentifiableRunnable> deadRunnablesQueue) { 
      this.pool = pool; 
      this.deadRunnablesQueue = deadRunnablesQueue; 
     } 

     @Override 
     public void run() { 
      while (true) { 
       IdentifiableRunnable r = null; 
       System.out.println(""); 
       System.out 
         .println("Supervisor will wait for a new runnable in order to resubmit it..."); 
       try { 
        System.out.println(); 
        r = deadRunnablesQueue.take(); 
       } catch (InterruptedException e) { 
       } 
       if (r != null) { 
        System.out.println("Supervisor got runnable [" + r.getId() 
          + "] to resubmit "); 
        pool.submit(r); 
       } 
      } 
     } 
    } 

    static class R1 implements IdentifiableRunnable { 
     private final String id = "R1"; 
     private long l; 

     @Override 
     public void run() { 
      while (true) { 
       System.out.println("R1 " + (l++)); 
       try { 
        Thread.currentThread().sleep(5000); 
       } catch (InterruptedException e) { 
        System.err.println("R1 InterruptedException:"); 
       } 
      } 
     } 

     public String getId() { 
      return id; 
     } 
    } 

    static class R2 implements IdentifiableRunnable { 
     private final String id = "R2"; 
     private long l; 

     @Override 
     public void run() { 
      try { 
       while (true) { 
        System.out.println("R2 " + (l++)); 
        try { 
         Thread.currentThread().sleep(5000); 
        } catch (InterruptedException e) { 
         System.err.println("R2 InterruptedException:"); 
        } 
        if (l == 3) { 
         throw new RuntimeException(
           "R2 error.. Should I continue to process ? "); 
        } 
       } 
      } catch (final Throwable t) { 
       t.printStackTrace(); 
       Test2.reSubmit(this); 
      } 
     } 

     public String getId() { 
      return id; 
     } 
    } 

} 

Bạn có thể thử để nhận xét ra Test2.reSubmit (this) để thấy rằng không có nó, R2 sẽ ngừng làm việc.

+0

Làm rõ: thực sự ScheduledExecutorService hoạt động với khối try trong phương thức run(). Ví dụ trên được dựa trên ExecutorService thay thế. – Rodolfo

+0

Cảm ơn bạn đã chia sẻ mã của mình. Đó là một ví dụ tốt mặc dù, nhìn qua phức tạp. – user454322

2

Hãy thử VerboseRunnable lớp từ jcabi-log, mà hiện các gói đề xuất bởi TofuBeer:

import com.jcabi.log.VerboseRunnable; 
Runnable runnable = new VerboseRunnable(
    Runnable() { 
    public void run() { 
     // do business logic, may Exception occurs 
    } 
    }, 
    true // it means that all exceptions will be swallowed and logged 
); 

Bây giờ, khi ai gọi runnable.run() không có ngoại lệ được ném ra. Thay vào đó, chúng được nuốt và đăng nhập (để SLF4J).

+0

Nice, 'Exception's được nuốt bằng cách sử dụng' VerboseRunnable', vì vậy các tác vụ tiếp theo sẽ được thực thi. – user454322

1

Nếu tất cả những gì bạn muốn là thực thi tiếp theo sẽ xảy ra và tiếp tục ngay cả sau khi ngoại lệ, mã này sẽ hoạt động.

ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();  

Runnable task = new Runnable() {  
    @Override 
    public void run() { 
    try{ 
     System.out.println(new Date() + " printing"); 
     if(true) 
     throw new RuntimeException(); 

    } catch (Exception exc) { 
     System.out.println(" WARN...task will continiue"+ 
      "running even after an Exception has araised"); 
    } 
    }  
}; 

executor.scheduleAtFixedRate(task, 0, 3, TimeUnit.SECONDS); 

Nếu một Throwable khác hơn Exception đã xảy ra bạn có thể không muốn hành tiếp theo được thực thi.

Đây là kết quả

Fri 23 tháng 11 12:09:38 JST 2012 in
_WARN ... nhiệm vụ sẽ continiuerunning ngay cả sau khi một ngoại lệ đã nâng
Fri 23 tháng 11 00:09:41 JST 2012 in
_WARN ... nhiệm vụ sẽ continiuerunning ngay cả sau khi ngoại lệ đã tăng
Thứ Sáu ngày 23 tháng 11 12:09:44 JST 2012 in
_WARN ...nhiệm vụ sẽ continiuerunning ngay cả sau khi một ngoại lệ đã nâng
Fri 23 Tháng 11 12:09:47 JST 2012 in
_WARN ... nhiệm vụ sẽ continiuerunning ngay cả sau khi một ngoại lệ đã nâng

Các vấn đề liên quan