Sfortunatamente la soluzione è difettosa. C'è una specie di bug con ScheduledThreadPoolExecutor
, anche riportato in this question: l'annullamento di un'attività inoltrata non rilascia completamente le risorse di memoria associate all'attività; le risorse vengono rilasciate solo quando l'attività scade.
Se si crea quindi uno TimeoutThreadPoolExecutor
con una scadenza piuttosto lunga (un utilizzo tipico) e si inoltrano le attività abbastanza velocemente, si finisce col riempire la memoria, anche se le attività sono state effettivamente completate correttamente.
si può vedere il problema con il seguente (molto grezzo) programma di test:
public static void main(String[] args) throws InterruptedException {
ExecutorService service = new TimeoutThreadPoolExecutor(1, 1, 10, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(), 10, TimeUnit.MINUTES);
//ExecutorService service = Executors.newFixedThreadPool(1);
try {
final AtomicInteger counter = new AtomicInteger();
for (long i = 0; i < 10000000; i++) {
service.submit(new Runnable() {
@Override
public void run() {
counter.incrementAndGet();
}
});
if (i % 10000 == 0) {
System.out.println(i + "/" + counter.get());
while (i > counter.get()) {
Thread.sleep(10);
}
}
}
} finally {
service.shutdown();
}
}
Il programma esaurisce la memoria disponibile, anche se attende il deposto le uova Runnable
s per completare.
Ho pensato a questo per un po ', ma sfortunatamente non sono riuscito a trovare una buona soluzione.
MODIFICA: Ho scoperto che questo problema è stato segnalato come JDK bug 6602600 e sembra che sia stato risolto molto recentemente.
È che 'ora di inizio' del timeout momento della presentazione? O il tempo in cui l'attività inizia ad essere eseguita? –
Buona domanda. Quando inizia l'esecuzione. Presumibilmente usando l'hook 'protected void beforeExecute (Thread t, Runnable r)'. –
@ scompt.com stai ancora utilizzando questa soluzione o è stata sostituita –