Executors Framework
Как сказано в Ответе kofemann , используйте threads для запуска кода в фоновом режиме. Но обработка потоков напрямую - сложное дело. Таким образом, платформа Executors была добавлена к Java, чтобы упростить эту работу.
В частности, вы хотите, чтобы ScheduledExecutorService
выполнял какую-то задачу снова и снова , Используйте класс Executors
, чтобы получить экземпляр ScheduledExecutorService
, поддерживаемый пулом из одного или нескольких потоков. Дайте этой задаче объект Runnable
, метод run
которого выполняет желаемую задачу. Укажите начальную задержку или ноль, чтобы начать немедленно. И укажите период, количество времени, которое должно пройти перед повторным выполнением задачи.
Важно: обязательно завершите работу службы исполнителя, когда она вам больше не нужна или когда ваше приложение закрывается. В противном случае потоки могут продолжать работать бесконечно.
Вот класс Count
для хранения нашего целого числа.
package work.basil.example;
public class Count
{
private int count;
public Count ( int count )
{
this.count = count;
}
public int getCount ( ) { return this.count; }
}
А вот пример кода. Мы определяем работоспособный объект, настраиваем службу исполнителя, запускаем ее, ждем некоторое время, затем выключаем службу исполнителя.
Count count = new Count( 42 );
Runnable runnable = ( ) -> {
int i = count.getCount();
System.out.println( "Count is currently: " + i + " at " + ZonedDateTime.now() );
};
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
long delay = 0;
long period = 5;
ses.scheduleAtFixedRate( runnable , delay , period , TimeUnit.SECONDS );
// … eventually shutdown your executor service and its backing thread pool.
try
{
Thread.sleep( TimeUnit.MINUTES.toMillis( 1 ) );
}
catch ( InterruptedException e )
{
e.printStackTrace();
}
ses.shutdown();
System.out.println( "Done running example of scheduled executor service." );
При запуске.
Количество в настоящее время: 42 в 2020-04-25T13: 08: 14.484127-07: 00 [America / Los_Angeles]
Счет в настоящее время: 42 в 2020-04-25T13: 08: 19.465306-07: 00 [America / Los_Angeles]
…
В настоящее время счетчик: 42 в 2020-04-25T13: 09: 14.460006-07: 00 [America / Los_Angeles]
Выполнен пример запуска службы запланированного исполнителя.
Совместное использование ресурсов между потоками, в данном случае экземпляр Count
и содержащаяся в нем переменная int
несут сложности. Изучите превосходную книгу Java Параллелизм на практике Брайана Гетца и др.
Я предполагаю, что вы намереваетесь увеличить этот счет во время выполнения вашего приложения , Если это так, мы должны защитить доступ к счетчику, потому что один поток может изменять число, в то время как другой читает его.
Java предоставляет класс AtomicInteger
для этой цели. Измените примитив int
в нашем классе Count
, чтобы использовать вместо него объект AtomicInteger
. Мы добавили метод increment
, чтобы увеличить значение этого AtomicInteger
. И мы используем поточно-безопасный метод AtomicInteger::get
для получения его значения.
package work.basil.example;
import java.util.concurrent.atomic.AtomicInteger;
public class Count
{
private AtomicInteger count;
public Count ( int count )
{
this.count = new AtomicInteger( count );
}
public int getCount ( ) { return this.count.get(); }
public int increment ( ) { return this.count.incrementAndGet(); }
}
Нам не нужно вносить какие-либо изменения в наш код, который использует класс Count
.
Если вы хотите увидеть увеличение действия, настройте еще одну задачу Runnable
. Запланируйте эту задачу на службе исполнителя, а также на других наших Runnable
.
Count count = new Count( 42 );
Runnable runnable = ( ) -> {
int i = count.getCount();
System.out.println( "Count is currently: " + i + " at " + ZonedDateTime.now() );
};
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
long delay = 0;
long period = 5;
ses.scheduleAtFixedRate( runnable , delay , period , TimeUnit.SECONDS );
Runnable runnableIncrementor = ( ) -> {
int i = count.increment();
System.out.println( "Incrementing count: " + i + " at " + ZonedDateTime.now() );
};
ses.scheduleAtFixedRate( runnableIncrementor , 7 , 13 , TimeUnit.SECONDS );
// … eventually shutdown your executor service and its backing thread pool.
try
{
Thread.sleep( TimeUnit.MINUTES.toMillis( 1 ) );
}
catch ( InterruptedException e )
{
e.printStackTrace();
}
ses.shutdown();
System.out.println( "Done running example of scheduled executor service." );
При запуске.
Счет в настоящее время: 42 в 2020-04-25T13: 26: 14.405538-07: 00 [America / Los_Angeles]
Счет в настоящее время: 42 в 2020-04-25T13: 26: 19.372358-07: 00 [America / Los_Angeles]
Увеличение счетчика: 43 в 2020-04-25T13: 26: 21.379639-07: 00 [ Америка / Лос-Анджелес]
Количество в настоящее время: 43 в 2020-04-25T13: 26: 24.371442-07: 00 [Америка / Лос-Анджелес]
…