Если у меня есть класс, который реализует java.lang.Runnable
, технически ничего не остановить несколько потоков от вызова run
одновременно на то же экземпляр Runnable
. Пример:Должны ли реализации Runnable допускать одновременные вызовы run() в одном экземпляре?
Runnable r = new MyRunnable();
//start thread 1
new Thread(r).start();
//start thread 2
new Thread(r).start();
Это не проблема, если метод run
полностью «самодостаточный» (т.е. не зависит от каких-либо частных членов экземпляра), потому что нет переменных разделяемых между потоками, так что ваш Runnable
никогда не может получить «поврежденное» внутреннее состояние. Но я думаю, что в большинстве случаев у вашего будет есть некоторые частные члены экземпляра, которые он манипулирует в run
, так что делать?
Чтобы использовать пример, мой класс MyRunnable
имеет поле mode
. Основная цель состоит в том, чтобы чисто остановить метод run
(установив mode
на STOPPED
), но он также имеет другие виды использования.
public static class MyRunnable implements Runnable
{
enum Mode { RUNNING, PAUSED, STOPPED, FASTFORWARDING, REWINDING; }
private volatile Mode mode;
@Override
public void run()
{
mode = Mode.RUNNING;
while (mode != Mode.STOPPED)
{
//do stuff. possibly other changes to the mode.
}
}
public void setMode(Mode mode)
{
this.mode = mode;
}
public Mode getMode()
{
return mode;
}
}
Как вы можете видеть, если я исполню несколько потоков одновременно для же экземпляра MyRunnable
(как показано выше), любые изменения в mode
может повлиять одновременно запущенных потоков по-разному. Например, если поток устанавливает mode
в STOPPED
, другой поток может изменить mode
на что-то еще, прежде чем каждый другой поток даже увидит, что он установлен в STOPPED
. Это может легко предотвратить поток, выходящий из цикла while.
Итак, как мне создать Runnable
как «одновременно применимый»? Возможно ли это? Разве это не стоит? Есть ли что-то вроде атрибута C# ThreadStatic, который я могу использовать (который, я думаю, был бы идеальным в этом контексте)?