2009-12-19 21 views
21

Đối với ứng dụng của tôi, tôi tạo công ăn việc làm và lên lịch cho họ với CronTriggers. Mỗi công việc chỉ có một kích hoạt và cả tên công việc và tên trình kích hoạt đều giống nhau. Không có công việc nào chia sẻ trình kích hoạt.Quartz Java tiếp tục một công việc excecutes nó nhiều lần

Bây giờ, khi tôi tạo trình kích hoạt cron như thế này "0/1 * * * *?" chỉ thị công việc thực hiện mỗi giây, nó hoạt động tốt.

Vấn đề tăng khi tôi lần đầu tiên tạm dừng công việc bằng cách gọi:

scheduler.pauseJob(jobName, jobGroup); 

và sau đó nối lại công việc sau khi giả sử 50 giây với:

scheduler.resumeJob(jobName, jobGroup); 

gì tôi thấy là đối với những 50 giây công việc không thực hiện theo yêu cầu. Nhưng thời điểm tôi tiếp tục công việc tôi thấy 50 thực hiện công việc cùng một lúc !!!

Tôi nghĩ rằng điều này là do các thiết lập mặc định cho hướng dẫn Misfire nhưng ngay cả sau khi cài đặt instruciton Misfire của cò khi tạo như sau:

trigger.setMisfireInstruction(CronTrigger.MISFIRE_INSTRUCTION_DO_NOTHING); 

Điều tương tự cũng xảy ra. Bất cứ ai có thể đề xuất một cách để sửa lỗi này?

Trả lời

27

CronTrigger hoạt động bằng cách ghi nhớ nextFireTime. Sau khi tạo trình kích hoạt, nextFireTime được khởi tạo. Mỗi lần công việc được kích hoạt nextFireTime được cập nhật. Vì công việc không được kích hoạt khi tạm dừng nextFireTime vẫn còn "cũ". Vì vậy, sau khi bạn tiếp tục công việc, kích hoạt sẽ trả về mọi thời gian kích hoạt cũ.

Vấn đề là, trình kích hoạt không biết nó đang bị tạm dừng. Để khắc phục điều này, việc xử lý này không được thực hiện. Sau khi tiếp tục công việc, phương thức updateAfterMisfire() của trình kích hoạt sẽ được gọi để sửa lỗi nextFireTime. Nhưng không nếu sự khác biệt giữa nextFireTime và bây giờ nhỏ hơn misfireThreshold. Sau đó, phương pháp này không bao giờ được gọi. Giá trị mặc định của ngưỡng này là 60.000. Do đó, nếu khoảng thời gian tạm dừng của bạn dài hơn 60 thì mọi thứ sẽ ổn.

Vì bạn gặp sự cố, tôi cho là không. ;) Để workaround này, bạn có thể sửa đổi các ngưỡng hoặc sử dụng một wrapper đơn giản xung quanh CronTrigger:

public class PauseAwareCronTrigger extends CronTrigger { 
    // constructors you need go here 

    @Override 
    public Date getNextFireTime() { 
     Date nextFireTime = super.getNextFireTime(); 
     if (nextFireTime.getTime() < System.currentTimeMillis()) { 
      // next fire time after now 
      nextFireTime = super.getFireTimeAfter(null); 
      super.setNextFireTime(nextFireTime); 
     } 
     return nextFireTime; 
    } 
} 
+4

Cảm ơn bạn sooo nhiều :) điều này làm việc như một say mê. Có vẻ lạ khi một nhiệm vụ đơn giản như tạm dừng một công việc sẽ tạo ra các vấn đề như thế này. –

5

Nếu bạn tạm dừng công việc, trình kích hoạt sẽ tiếp tục kích hoạt, nhưng các lệnh thực thi sẽ được xếp hàng cho đến khi công việc được tiếp tục. Đây không phải là kích hoạt không phù hợp, do đó cài đặt đó sẽ không có hiệu lực.

Điều bạn muốn làm, theo tôi lập trình là vô hiệu hoá hoặc loại bỏ kích hoạt cron, thay vì tạm dừng công việc. Khi bạn muốn tiếp tục, sau đó thêm lại trình kích hoạt.

+0

javadoc cho phương thức pauseJob nói "Tạm dừng JobDetail với tên đã cho - bằng cách tạm dừng tất cả các Trình kích hoạt hiện tại của nó." vì vậy tôi đoán kích hoạt đang bị tạm dừng. Ngoài ra không có phương pháp tạm dừng trên kích hoạt chính nó. Hoặc bất cứ điều gì tương tự như nó. Chỉ đơn giản là loại bỏ các kích hoạt từ công việc và reinserting nó lựa chọn duy nhất của tôi để tạm dừng một công việc? Tôi có nghĩa là đây là một điều khá tầm thường để muốn lịch trình của bạn để làm. Làm thế nào đến nó không chỉ đơn giản là làm việc? –

+0

Hmm, điểm tốt. Tôi thấy rằng với Quartz, cố gắng nhiều thứ cho đến khi một cái gì đó hoạt động là cách tiếp cận hiệu quả nhất, vì nó không phải lúc nào cũng làm những gì nó nói trên tin. – skaffman

+0

Điều này cực kỳ bực bội vì cũng không có cách nào đơn giản để loại bỏ trình kích hoạt khỏi công việc. Tôi có thể có một công việc ít hoạt động hơn không? và nếu có, làm thế nào? Ý tưởng nào? Tôi bắt đầu mất kiên nhẫn của tôi với điều này, tôi đã cố gắng cho giờ :) –

1

Kể từ 1.6.5 ít nhất (phiên bản sớm nhất của thạch anh trong tầm tay của tôi), chức năng lịch có một phương pháp pauseTrigger rằng lấy tên/nhóm làm tham số. Điều này có nghĩa là bạn không cần phải có một lớp phụ của mọi loại trình kích hoạt mà bạn sử dụng, cũng như bạn không phải thực hiện các thủ thuật xóa/chèn phức tạp.

Cả hai điều này đều quan trọng đối với tôi vì 1) cơ sở dữ liệu của chúng tôi có chính sách không xóa nghiêm ngặt và 2) kho dữ liệu tùy chỉnh mà tôi sử dụng không hỗ trợ các lớp con kích hoạt.

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