2012-04-17 3 views
4

Я новичок в Java, и я не работал с потоками в прошлом. Теперь у меня есть очень сложная проблема для моего уровня знаний.Синхронизация двух таймеров с несколькими экземплярами (Java)

Я разработал две функции «Отправить почту» и «Проверить почту». Каждый пользователь зарегистрировать свои предпочтения и система создает два каталога с большим количеством инструкций для периодической работы как

A) отправить сообщение каждый 1500 мс

B) отправить сообщение каждые 1800 мс

C) отправить сообщение каждые 3000 мс

И А) проверка сообщение каждые 2000 мс

B) проверка сообщения каждые 6000 мс

C) проверить сообщение каждые 8000 мсек

Я пробовал много способов с потоками, но я не могу это сделать. Мой вопрос - это лучший способ их синхронизации? Ниже приведен код моего последнего усилия с использованием потоков.

public class MailCreatorThread extends Thread { 
    @Override 
    public void run() { 
     CreateMail(_date); //creates a mail with _date as subject 
    } 
} 

public class GPSThread extends Thread { 
    @Override 
    public void run() { 
     // TODO Auto-generated method stub 
     while (!_isTimeToStop) { 
      try { 
       while (_servicesToUpdate.size() == 0) { 
        Thread.sleep(500); 
       } 
       _currentService = (MyService) _servicesToUpdate.get(0) 
         .clone(); 
       _servicesToUpdate.remove(0); 

         MailCreatorThread mailCreatorThread = new MailCreatorThread(); 
         mailCreatorThread.start(); 


      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

public class CheckServicesThread extends Thread { 
    @Override 
    public void run() { 
     // TODO Auto-generated method stub 
     while (!_isTimeToStop) { 
      try { 
       Thread.sleep(1000); 
        for (int j = 0; j < _servicesList.length; j++) { 
         MyService currentService = ((MyService) _servicesList[j]); 
         if (myService.getTimeToNextUpdate() - 1000 <= 0) { 
          _servicesToUpdate 
            .add((MyService) currentService 
              .clone()); 
          currentService 
            .setTimeToNextUpdate(currentService 
              .getUpdatePeriod()); 
         } else { 
          currentService 
            .setTimeToNextUpdate(currentService 
              .getTimeToNextUpdate() - 1000); 
         } 
       } 

      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
     stopSelf(); 
    } 
} 

ответ

4

Вы можете использовать ScheduledExecutorService для выполнения периодических задач. Синтаксис довольно прост:

Runnable check = new Runnable() { 
    public void run() { 
     checkMessage(); 
    } 
} 
Runnable send = new Runnable() { 
    public void run() { 
     sendMessage(); 
    } 
} 

//since what you are doing is mostly I/O you probably want to have 
//more than one thread available so that if one operation blocks, 
//the other ones can be launched in parallel 

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(10); 
scheduler.scheduleAtFixedRate(check, 0, 1500, MILLISECONDS); 
scheduler.scheduleAtFixedRate(send, 0, 6000, MILLISECONDS); 

Примечание: Timer упоминается в Ozzy's answer не должны использоваться больше, как это было в Java 1.5 улучшена за счет ScheduledThreadPoolExecutor, как объяснено в Timer's javadoc:

Java 5.0 введена java.util.параллельный пакет и одна из утилит параллелизма в нем - это ScheduledThreadPoolExecutor, который является пулом потоков для многократного выполнения задач с заданной скоростью или задержкой. Это эффективно более универсальная замена комбинации Timer/TimerTask, поскольку она позволяет несколько потоков обслуживания, принимает различные единицы времени и не требует подкласса TimerTask (просто реализовать Runnable). Настройка ScheduledThreadPoolExecutor с одним потоком делает его эквивалентным таймеру.

+0

Спасибо! Я пробовал ваше решение, и оно отлично работает! – Bilias7

3

В java у вас есть встроенные классы Timer и TimerTask, которые помогут вам выполнить задачу в отдельном потоке.

Это позволит создать таймер, который будет создавать свой собственный фон тему:

Timer t = new Timer(); 

Вы можете запланировать, как много задач, как вы хотите, чтобы этот таймер, они будут делить собственный поток таймера.

Это, как вы можете запланировать одну задачу по резьбе таймера, после задержки 2000 мс = 2s:

t.schedule(new TimerTask() { 
    @Override 
    public void run() { 
     //task to perform 
    } 
}, 2000); 

Это, как вы можете запланировать повторил задачу на резьбе таймера, после задержка 1 сек, и повторить задачу на 1.5s интервалы:

t.scheduleAtFixedRate(new TimerTask() { 
    @Override 
    public void run() { 
     //task to perform every 1.5 seconds 
    } 
}, 1000, 1500); 

Теперь у вас есть выбор, чтобы запланировать обе задачи (CheckMail, Sendmail) к одному таймеру (та же нить) или дать каждому из них свой собственный таймер (отдельные потоки).

Для получения дополнительной информации обратитесь к яве документации (http://docs.oracle.com/javase/6/docs/api/java/util/Timer.html)

Надеется, что это помогает.

+0

Вы должны порекомендовать использовать 'ScheduledThreadPoolExecutor' вместо' Timer' для Java 1.5+ - см. Мой ответ. – assylias

+0

Оззи благодарю вас за ваше время! Я пробовал ваше решение, и оно работает точно так же, как вы описываете , но после некоторого поиска в java я получаю это, поскольку assylias говорит, что ScheduledExecutorService является рекомендуемым инструментом. – Bilias7