Supongamos que tengo un ExecutorService (que puede ser un grupo de subprocesos, por lo que hay concurrencia) que ejecuta una tarea varias veces, ya sea periódicamente o en respuesta a alguna otra condición. La tarea que se ejecutará es el siguiente:java: ejecutores + tareas + bloqueos
- si esta tarea ya está en marcha, no hacer nada (y dejar que el acabado de la tarea a ejecutar previamente).
- si esta tarea aún no está en curso, ejecute Algorithm X, que puede llevar mucho tiempo.
Estoy tratando de pensar en una forma de implementar esto. Debe ser algo así como:
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
donde SomeObj
es o bien un ReentrantLock (= tryLock()
adquirir y liberar = unlock()
) o un AtomicBoolean o algo, pero no estoy seguro de qué. ¿Necesito un ReentrantLock aquí? (Tal vez quiero un bloqueo no reentrante en caso de que algorithmX()
haga que esta tarea se ejecute de forma recursiva). ¿O sería suficiente un AtomicBoolean?
editar: para un bloqueo sin reentrada, ¿es esto apropiado?
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.
*/
}
}
Una recomendación: en lugar de presentar un código complejo y pedirle a alguien que lo valide, pruébelo usted mismo y luego, si encuentra un comportamiento que no comprende, formule una pregunta específica. –
gracias ... No es que busque validar el código, es que tengo una situación en la que necesito ejecutar una tarea en serie en un sistema multiproceso, y no estoy seguro de cómo implementarlo correctamente de cara a problemas de concurrencia. El código que presenté es simplemente un intento de ejemplo. Si, en su lugar, debería utilizar una clase existente, me gustaría saberlo, porque estoy buscando qué pregunta exacta formular. –
Mi experiencia con los problemas de simultaneidad es que, si bien puede probar el código para ver si hay errores obvios, no puede simplemente intentar verificar si tiene éxito, porque puede haber condiciones extrañas e improbables que mostrarán que su programa es incorrecto. , y puede que no sea posible reproducir esas condiciones bajo demanda. –