Ho un requisito per l'esecuzione di un'attività in modo asincrono mentre si eliminano ulteriori richieste fino al completamento dell'attività.Singolo threading di un'attività senza accodamento ulteriori richieste
La sincronizzazione del metodo solo accoda le attività e non salta. Inizialmente pensavo di utilizzare un SingleThreadExecutor ma che accoda anche le attività. Ho quindi esaminato ThreadPoolExecutor ma legge la coda per ottenere l'esecuzione dell'attività e pertanto eseguirà un task in esecuzione e almeno un task in coda (gli altri possono essere eliminati utilizzando ThreadPoolExecutor.DiscardPolicy).
L'unica cosa che posso pensare è usare un semaforo per bloccare la coda. Sono venuto con il seguente esempio per mostrare quello che sto cercando di ottenere. c'è un modo più facile? Ho perso qualcosa di ovvio?
import java.util.concurrent.*;
public class ThreadPoolTester {
private static ExecutorService executor = Executors.newSingleThreadExecutor();
private static Semaphore processEntry = new Semaphore(1);
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 20; i++) {
kickOffEntry(i);
Thread.sleep(200);
}
executor.shutdown();
}
private static void kickOffEntry(final int index) {
if (!processEntry.tryAcquire()) return;
executor.
submit(
new Callable<Void>() {
public Void call() throws InterruptedException {
try {
System.out.println("start " + index);
Thread.sleep(1000); // pretend to do work
System.out.println("stop " + index);
return null;
} finally {
processEntry.release();
}
}
}
);
}
}
uscita Esempio
start 0
stop 0
start 5
stop 5
start 10
stop 10
start 15
stop 15
Prendendo la risposta di axtavt e trasformando l'esempio precedente ha pronunciato la seguente soluzione più semplice.
import java.util.concurrent.*;
public class SyncQueueTester {
private static ExecutorService executor = new ThreadPoolExecutor(1, 1,
1000, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),
new ThreadPoolExecutor.DiscardPolicy());
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 20; i++) {
kickOffEntry(i);
Thread.sleep(200);
}
executor.shutdown();
}
private static void kickOffEntry(final int index) {
executor.
submit(
new Callable<Void>() {
public Void call() throws InterruptedException {
System.out.println("start " + index);
Thread.sleep(1000); // pretend to do work
System.out.println("stop " + index);
return null;
}
}
);
}
}
scovare mi dici, perché si preferisce usare un DiscardPolicy sulla cattura della RejectedExecutionException? –