Предположим, что у меня есть ExecutorService (который может быть пулом потоков, поэтому есть параллелизм), который выполняет задачу в разное время, периодически или в ответ на какое-то другое условие. Задача, которая должна быть выполнена, следующая:java: executors + tasks + locks
- Если эта задача уже выполняется, ничего не предпринимайте (и пусть закончившаяся работа заканчивается).
- Если эта задача еще не выполняется, запустите Алгоритм X, который может занять много времени.
Я пытаюсь придумать способ реализации этого. Это должно быть что-то вроде:
Runnable task = new Runnable() {
final SomeObj inProgress = new SomeObj();
@Override public void run() {
if (inProgress.acquire())
{
try
{
algorithmX();
}
finally
{
inProgress.release();
}
}
}
}
// re-use this task object whenever scheduling the task with the executor
где SomeObj
является либо ReentrantLock (приобретение = tryLock()
и отпустить = unlock()
) или AtomicBoolean или что-то, но я не уверен,. Мне нужен ReentrantLock здесь? (Возможно, я хочу блокировку без реентера в случае, если algorithmX()
заставляет эту задачу запускать рекурсивно!) Или достаточно было бы AtomicBoolean?
изменить: для блокировки, не являющейся реентерабельным, это подходит?
Runnable task = new Runnable() {
boolean inProgress = false;
final private Object lock = new Object();
/** try to acquire lock: set inProgress to true,
* return whether it was previously false
*/
private boolean acquire() {
synchronized(this.lock)
{
boolean result = !this.inProgress;
this.inProgress = true;
return result;
}
}
/** release lock */
private void release() {
synchronized(this.lock)
{
this.inProgress = false;
}
}
@Override public void run() {
if (acquire())
{
// nobody else is running! let's do algorithmX()
try
{
algorithmX();
}
finally
{
release();
}
}
/* otherwise, we are already in the process of
* running algorithmX(), in this thread or in another,
* so don't do anything, just return control to the caller.
*/
}
}
Рекомендация: вместо того, чтобы представлять сложный код и просить кого-то его проверить, попробуйте сами, а затем, если вы столкнулись с поведением, которое вы не понимаете, задайте конкретный вопрос. –
спасибо ... Это не то, что я ищу, чтобы проверить код, это то, что у меня есть ситуация, когда мне нужно запускать задачу поочередно в многопоточной системе, и я не уверен, как правильно ее реализовать перед лицом проблемы параллелизма. Представленный мной код представляет собой просто попытку на примере. Если вместо этого я должен использовать существующий класс, я хотел бы знать это, потому что я возился с каким точным вопросом. –
Мой опыт с проблемами параллелизма заключается в том, что, хотя вы можете попробовать код, чтобы увидеть, есть ли очевидные ошибки, вы не можете просто попробовать его проверить, удастся ли ему, потому что могут быть странные невероятные угловые условия, которые покажут вашу программу неверной , и может быть невозможно воспроизвести эти условия по требованию. –