2016-11-15 3 views
1

Я использую Spring ThreadPoolTaskExecutor в моем приложении. Один из моих методов нужно вызывать только в полночь пятницы. Этот метод вызова на сервере startup.So Я использую Thread.sleep() следующим образомАльтернатива для Thread.sleep() в java

 Calendar today = Calendar.getInstance(); 
     int dayOfWeek = today.get(Calendar.DAY_OF_WEEK); 
     int daysUntilNextFriday = Calendar.FRIDAY - dayOfWeek; 
     if(daysUntilNextFriday < 0){ 
      daysUntilNextFriday = daysUntilNextFriday + 7; 
     } 


     Calendar c = Calendar.getInstance(); 

     c.add(Calendar.DAY_OF_YEAR, daysUntilNextFriday); 
     c.set(Calendar.HOUR_OF_DAY, 0); 
     c.set(Calendar.MINUTE, 0); 
     c.set(Calendar.SECOND, 0); 
     Date d1 = c.getTime(); 

     long diffTime = d1.getTime() - new Date().getTime(); 

     Thread.sleep(diffTime); 

В некоторых случаях это может ждать более чем на 1 день, а также. Есть ли лучший подход вместо использования Thread.sleep(). Я видел в некоторых местах использование Thread.sleep() будет проблемой производительности. В моем случае есть ли альтернатива для улучшения производительности?

Первоначально мы планировали около 50 сервисов с помощью ThreadPoolTaskExecutor. некоторые из услуг, которые не начинают должным образом .Мы не смогли найти точный вопрос из прошлого 1 month.So мы хотели попробовать с исполнителем

Пожалуйста, обратитесь эту Spring scheduler is stopping unexpectedly and starting again

+0

Вы должны использовать планировщик кварца или cron для программ, которые необходимо периодически запускать в определенное время в определенный день. – RealSkeptic

+0

«Улучшить производительность»? Производительность действительно не вызывает беспокойства, если вы спите в течение дня. Большая проблема, с которой вы столкнулись, заключается в том, что ваша JVM все еще работает. –

+0

Я бы лично использовал cronjob, планировщик, ExecutorService или что-то подобное. Потому что Thread.sleep в течение одной недели кажется расточительным. –

ответ

1

Вы сказали в комментариях вы используете Весна. Таким образом, вы можете использовать выражение cron. Подробнее о том, как использовать Scheduler см. 34. Task Execution and Scheduling.

@Scheduled(cron="0 0 1 ? * FRI *") 
public void doSomething() { 
    // do stuff 
} 

Это позволит запустить его в пятницу в пятницу 1 час. Вы можете использовать Cron Maker для генерации выражений.

В вашем классе конфигурации вы должны включить планирование через.

@Configuration 
@EnableAsync 
@EnableScheduling 
public class AppConfig { 
} 
+0

Спасибо Murat. Но есть ли возможность без использования планирования i.e с исполнителем – PSR

+0

@PSR Почему вы пытаетесь избежать использования планировщика? Он относится к одной и той же структуре, и это правильный инструмент в этой структуре для выполнения задач в определенный день и время. – RealSkeptic

+0

@PSR Нет смысла избегать планировщика, потому что он будет делать то, что вы хотите. –

0

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

ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); 
     scheduler.schedule(() -> { 
      /* 
      * define work to be done inside this lambda 
      */ 
     }, diffTime, TimeUnit.MILLISECONDS); 

Примечание: если вы хотите работать случиться каждую пятницу в полночь (поэтому не только в эту пятницу), вы можете изменить команду по расписанию произойдет в заданном интервале:

scheduler.scheduleAtFixedRate(() -> { 
    /* 
    * define work to be done inside this lambda 
    */ 
    }, diffTime, Duration.ofDays(7).toMillis(), TimeUnit.MILLISECONDS); 
0

использования ScheduledExecutorService:

private static final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); 

Если вы не беспокоитесь о точности (например, уход за перехода на летнее сдвигами):

Вы можете аппроксимировать фиксированную периодичность:

7 * 24 * 60 * 60 * 1000 = 604800000 (в неделю в мс)

Тогда вы можете назвать исполнителя, как это:

Runnable task = <your task extending Runnable>  
long difftime = <time to next friday>; 
long week = 7 * 24 * 60 * 60 * 1000; 

executor.scheduleAtFixedRate(task, difftime, week, TimeUnit.MILLISECONDS); 

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

Если вы являются беспокоитесь о точности: Тогда вместо называют:

executor.schedule(task, difftime, TimeUnit.MILLISECONDS); 

, который будет выполнять только свою задачу один раз.В вашей задаче - вызовите метод, который перепланирует задачу для следующего выполнения с недавно вычисленным difftime.

0

Как сообщают другие пользователи, используйте ThreadPoolTaskScheduler, он предусмотрен пружинным каркасом и находится в одном пакете ThreadPoolTaskExecutor.

Другим вариантом является ScheduledExecutorService, который предоставляется Core Java и имеет аналогичную функциональность.

Обе службы позволяют настраивать размер пула потоков (500 или все, что вы хотите). Но помните, что если ваши работники запускаются в разные временные рамки, вы можете повторно использовать меньшее количество потоков, особенно если они не работают в течение длительного периода времени.

Кроме того, убедитесь, что вы перехватываете все исключения, которые происходят у ваших работников, чтобы избежать неожиданных сбоев, которые вы наблюдаете.

Там два общих шаблонов для выполнения этого:

  1. Surround код работника в Try/поймать блока:

    public void run() { 
        try { 
         doRun(); 
        } catch (Throwable t) { 
         LOG.error("exception occurred in worker", t); 
        } 
    } 
    
  2. Использование UncaughtExceptionHandler для перехвата и регистрации отказов во всех потоках, где исключения не были перехватывается:

    public class DefaultUncaughtExceptionHandler implements UncaughtExceptionHandler { 
        static { 
         if (Thread.getDefaultUncaughtExceptionHandler() == null) { 
          Thread.setDefaultUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler()); 
         } 
        } 
    
        @Override 
        public void uncaughtException(Thread t, Throwable e) { 
         if (!(e instanceof ThreadDeath)) { 
          LOG.error("uncaught exception occurred in thread " + t.getName(), e); 
         } 
        } 
    } 
    
Смежные вопросы