В этом коде есть несколько ошибок. Вы не указали с помощью «есть какая-то проблема», но вот что выпрыгивает.
Во-первых, переменная counter
не обновляется безопасно. Несколько потоков не имеют гарантированной видимости последнего записанного значения; у вас также нет гарантии, что ни один другой поток не обновил свое значение между чтением и записью.
Простое решение этого: замените counter
на AtomicInteger
и используйте getAndIncrement
или incrementAndGet
для увеличения.
Во-вторых, public static class Runnable extends Thread {
является чрезвычайно сомнительным.
- Не скрывайте имена общеизвестных Java классов (это скрывается
java.lang.Runnable
) - Не расширяйте
Thread
напрямую, особенно когда все вы нужно java.lang.Runnable
для добавления выполнения с ExecutorService
.
Более подходящим объявлением класса будет:
public static class MyRunnable implements Runnable {
(или как вы хотите его назвать)
Или вы можете просто объявить анонимный класс:
executor.execute(new Runnable() { /* body */ });
Или вы можете просто объявить лямбду:
executor.execute(() -> { /* body */ });
В-третьих, count
не на самом деле, кажется, здесь нет очевидной цели. Лог c запускаемого объекта выглядит следующим образом:
- Если «flag» имеет значение false:
- Установить «flag» на true
- Увеличить переменную
- Установите «флаг» в false
- В противном случае:
- Подождите 3 секунды
- Попробуйте еще раз
count
играет здесь роль «флага». Фактически это просто AtomicBoolean
.
Но вам вообще не нужна отдельная переменная count
, если вы сделаете counter
an AtomicInteger
:
while (true) {
int current = counter.get();
if (counter.compareAndSet(current, current + 1)) {
// Nothing else is trying to update "current" at the same time:
// we updated it. Stop.
break;
}
// Something else is trying to update at the same time.
// Sleep for 3 seconds.
Thread.sleep(3000);
}