سؤال

أرغب في الحصول على java.utils.Timer بوقت قابل لإعادة التعيين في Java. أحتاج إلى تعيين حدث لمرة واحدة ليحدث خلال X ثانية.إذا لم يحدث أي شيء بين الوقت الذي تم فيه إنشاء المؤقت وX ثانية، فسيحدث الحدث كالمعتاد.

ومع ذلك، إذا قررت، قبل انقضاء X ثانية، أن الحدث يجب أن يقع بعد Y ثانية بدلاً من ذلك، فأنا أريد أن أكون قادرًا على إخبار المؤقت بإعادة ضبط وقته بحيث يقع الحدث خلال Y ثانية.على سبيل المثال.يجب أن يكون المؤقت قادرًا على القيام بشيء مثل:

Timer timer = new Timer();  
timer.schedule(timerTask, 5000); //Timer starts in 5000 ms (X)

//At some point between 0 and 5000 ms...  
setNewTime(timer, 8000);  //timerTask will fire in 8000ms from NOW (Y).

لا أرى طريقة للقيام بذلك باستخدام مؤقت الأدوات، كما لو قمت باستدعاء Cancel() فلن تتمكن من جدولته مرة أخرى.

الطريقة الوحيدة التي اقتربت بها من تكرار هذا السلوك هي استخدام javax.swing.Timer وتتضمن إيقاف المؤقت الأصلي وإنشاء مؤقت جديد.أي.:

timer.stop();
timer = new Timer(8000, ActionListener);
timer.start();

هل توجد طريقة أسهل؟؟

هل كانت مفيدة؟

المحلول

بحسب ال Timer الوثائق، في Java 1.5 وما بعده، يجب أن تفضل ScheduledThreadPoolExecutor بدلاً من.(قد ترغب في إنشاء هذا المنفذ باستخدام Executors.newSingleThreadScheduledExecutor() لسهولة الاستخدامإنه يخلق شيئًا يشبه إلى حد كبير ملف Timer.)

الشيء الرائع هو أنه عندما تقوم بجدولة مهمة (عن طريق الاتصال schedule()) ، تقوم بإرجاع أ ScheduledFuture هدف.يمكنك استخدام هذا لإلغاء المهمة المجدولة.يمكنك بعد ذلك إرسال مهمة جديدة بوقت تشغيل مختلف.

الوقت المتوقع للوصول:ال Timer الوثائق المرتبطة لا تقول أي شيء عنها ScheduledThreadPoolExecutor, ، ومع ذلك OpenJDK وكان الإصدار هذا ليقول:

قدمت جافا 5.0 java.util.concurrent الحزمة وواحدة من أدوات التزامن فيها هي ScheduledThreadPoolExecutor وهو تجمع مؤشرات ترابط لتنفيذ المهام بشكل متكرر بمعدل معين أو تأخير.إنه بديل أكثر تنوعا ل Timer/TimerTaskمزيج ، لأنه يسمح بتقنية سلسلة خدمة متعددة ، يقبل وحدات زمنية مختلفة ، ولا يتطلب التصنيف الفرعي TimerTask (فقط تنفيذ Runnable).تكوين ScheduledThreadPoolExecutor بخيط واحد يجعله يعادل Timer.

نصائح أخرى

إذا كان لديك Timer لن يكون هناك سوى مهمة واحدة لتنفيذها، لذا أقترح تصنيفها فرعيًا:

import java.util.Timer;
import java.util.TimerTask;

public class ReschedulableTimer extends Timer
{
    private Runnable  task;
    private TimerTask timerTask;

    public void schedule(Runnable runnable, long delay)
    {
        task = runnable;
        timerTask = new TimerTask()
        {
            @Override
            public void run()
            {
                task.run();
            }
        };
        this.schedule(timerTask, delay);
    }

    public void reschedule(long delay)
    {
        timerTask.cancel();
        timerTask = new TimerTask()
        {
            @Override
            public void run()
            {
                task.run();
            }
        };
        this.schedule(timerTask, delay);
    }
}

سوف تحتاج إلى العمل على الكود لإضافة فحوصات لسوء الاستخدام، ولكن يجب أن يحقق ما تريد.ال ScheduledThreadPoolExecutor لا يبدو أنه قد تم تصميمه لدعم إعادة جدولة المهام الحالية أيضًا، ولكن يجب أن يعمل نهج مماثل هناك أيضًا.

مقتطف الكود بأكمله يسير على هذا النحو ....آمل أن تكون المساعدة كاملة

{

        Runnable r = new ScheduleTask();
        ReschedulableTimer rescheduleTimer = new ReschedulableTimer();
        rescheduleTimer.schedule(r, 10*1000);


    public class ScheduleTask implements Runnable {
        public void run() {
            //Do schecule task

        }
      }


class ReschedulableTimer extends Timer {
        private Runnable task;
        private TimerTask timerTask;

        public void schedule(Runnable runnable, long delay) {
          task = runnable;
          timerTask = new TimerTask() { 
              public void run() { 
                  task.run(); 
                  }
              };

          timer.schedule(timerTask, delay);        
        }

        public void reschedule(long delay) {
            System.out.println("rescheduling after seconds "+delay);
          timerTask.cancel();
          timerTask = new TimerTask() { 
              public void run() { 
                  task.run(); 
              }
          };
          timer.schedule(timerTask, delay);        
        }
      }


}

هل تحتاج إلى جدولة مهمة متكررة؟في هذه الحالة أنصحك بالتفكير في استخدام كوارتز.

لا أعتقد أنه من الممكن القيام بذلك مع Timer/TimerTask, ، ولكن اعتمادًا على ما تريد تحقيقه بالضبط، قد تكون سعيدًا باستخدامه java.util.concurrent.ScheduledThreadPoolExecutor.

هذا ما أحاول.لدي فصل دراسي يقوم باستقصاء قاعدة بيانات كل 60 ثانية باستخدام TimerTask.

في صفي الرئيسي، أحتفظ بمثيل Timer، ومثيل للفئة الفرعية المحلية الخاصة بي من TimerTask.لدى الفئة الرئيسية طريقة لتعيين الفاصل الزمني للاستقصاء (على سبيل المثال، الانتقال من 60 إلى 30).فيه، أقوم بإلغاء TimerTask الخاص بي (وهو فئتي الفرعية، حيث قمت بالكتابة فوق طريقة الإلغاء () لإجراء بعض التنظيف، ولكن لا ينبغي أن يكون ذلك مهمًا) ثم أجعلها فارغة.أقوم بإعادة إنشاء مثيل جديد له، وجدولة المثيل الجديد في الفاصل الزمني الجديد في المؤقت الموجود.

نظرًا لعدم إلغاء Timer نفسه، يظل الخيط الذي كان يستخدمه نشطًا (وكذلك أي TimerTasks أخرى بداخله)، ويتم استبدال TimerTask القديم بآخر جديد، والذي يصادف أنه هو نفسه، ولكن VIRGIN (منذ القديم كان سيتم تنفيذه أو جدولته، ولم يعد عذراء، كما هو مطلوب للجدولة).

عندما أرغب في إيقاف تشغيل المؤقت بالكامل، أقوم بإلغاء TimerTask وإلغائه (كما فعلت عند تغيير التوقيت، مرة أخرى، لتنظيف الموارد في فئتي الفرعية من TimerTask)، ثم أقوم بإلغاء Timer نفسه وإلغائه.

فيما يلي مثال للمؤقت القابل لإعادة الضبط.حاول أن تغيره بما يناسبك..

package com.tps.ProjectTasks.TimeThread;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

/**
 * Simple demo that uses java.util.Timer to schedule a task to execute
 * every 5 seconds and have a delay if you give any input in console.
 */

public class DateThreadSheduler extends Thread {  
    Timer timer;
    BufferedReader br ;
    String data = null;
    Date dNow ;
    SimpleDateFormat ft;

    public DateThreadSheduler() {

        timer = new Timer();
        timer.schedule(new RemindTask(), 0, 5*1000); 
        br = new BufferedReader(new InputStreamReader(System.in));
        start();
    }

    public void run(){

        while(true){
            try {
                data =br.readLine();
                if(data != null && !data.trim().equals("") ){
                    timer.cancel();
                    timer = new Timer();
                    dNow = new Date( );
                    ft = new SimpleDateFormat ("E yyyy.MM.dd 'at' hh:mm:ss a zzz");
                    System.out.println("Modified Current Date ------> " + ft.format(dNow));
                    timer.schedule(new RemindTask(), 5*1000 , 5*1000);
                }

            }catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String args[]) {
        System.out.format("Printint the time and date was started...\n");
        new DateThreadSheduler();
    }
}

class RemindTask extends TimerTask {
    Date dNow ;
    SimpleDateFormat ft;

    public void run() {

        dNow = new Date();
        ft = new SimpleDateFormat ("E yyyy.MM.dd 'at' hh:mm:ss a zzz");
        System.out.println("Current Date: " + ft.format(dNow));
    }
}

يطبع هذا المثال التاريخ والوقت الحاليين كل 5 ثوانٍ...ولكن إذا قمت بإدخال أي إدخال في وحدة التحكم، فسيتم تأخير المؤقت لتنفيذ مهمة الإدخال المحددة...

لقد قمت بإنشاء فصل مؤقت خاص بي لغرض مماثل؛استخدمه بحرية:

public class ReschedulableTimer extends Timer {
  private Runnable mTask;
  private TimerTask mTimerTask;

  public ReschedulableTimer(Runnable runnable) {
    this.mTask = runnable;
  }

  public void schedule(long delay) {
    if (mTimerTask != null)
      mTimerTask.cancel();

    mTimerTask = new TimerTask() {
      @Override
      public void run() {
        mTask.run();
      }
    };
    this.schedule(mTimerTask, delay);
  }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top