Ich benutze Java ExecutorService (ThreadPool), um eine Aufgabe & UI zu aktualisieren, während eine bestimmte Aktivität im Vordergrund (sichtbar) ist.Java ExecutorService - Aufgabe/Callable nicht aufheben/unterbrechen
Problem: Was ich will, ist, wenn der Benutzer auf eine andere Tätigkeit schaltet ich will alle, die Aufgabe stoppen/abbrechen (ob der Warteschlange oder Laufen). Und dazu muss ich entweder ExecutorService Shutdown/ShutdownNow-Methode oder Abbrechen (true) auf Future-Objekt von ExecutorService senden Methode nach Überprüfung des Future-Objektstatus durch Aufruf von isDone(). Dies würde das entsprechende Thread-Flag für die Unterbrechung auf TRUE setzen, was ich überprüfen muss (Thread.currentThread.isInterrupted()) in meiner aufrufbaren Implementierung, um festzustellen, ob die Task/der Thread unterbrochen wurde. Problem ist, ob i ExecutorService Shutdown-Methode aufrufen oder zukünftige cancel (true) Verfahren in beiden Fällen selten 1 von 10-mal den Gewinde Unterbrechungs-Flag auf WAHR setzt die schließlich zu Speicherlecks führt usw.
Code:
Thread Singleton-Implementierung (cancelAll-to Aufgaben & shutdownExecutor-to Shutdown ExecutorService abbrechen):
private static class ThreadPoolManager {
private ExecutorService executorService;
private List<Future> queuedFutures;
private BlockingQueue<Runnable> blockingQueue;
private static ThreadPoolManager instance;
private ThreadPoolManager() {
MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "Threadpool-created(constructor)");
queuedFutures = new ArrayList<>();
blockingQueue = new LinkedBlockingDeque<>();
executorService = new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(), Runtime.getRuntime().availableProcessors(), 1, TimeUnit.SECONDS, blockingQueue);
}
static {
instance = new ThreadPoolManager();
}
public static void submitItemTest(Callable<Object> callable) {
MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "Threadpool-submitted item test");
if(instance.executorService.isShutdown()){
instance=new ThreadPoolManager();
}
Future future = instance.executorService.submit(callable);
instance.queuedFutures.add(future);
}
public static void submitTestAll(Callable<Object> callable) {
MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "Threadpool-submitted test all");
if(instance.executorService.isShutdown()){
instance=new ThreadPoolManager();
}
cancelAll();
Future future = instance.executorService.submit(callable);
instance.queuedFutures.add(future);
}
public static void cancelAll() {
MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "Cancelling all future tasks");
instance.blockingQueue.clear();
for (Future future : instance.queuedFutures) {
if (!future.isDone()) {
boolean cancelled = future.cancel(true);
MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "Cancelled-" + cancelled);
}
}
instance.queuedFutures.clear();
}
public static void shutdownExecutor(){
MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "Shuttingdown threadpool");
instance.executorService.shutdownNow();
}
}
aufrufbare Implementation (normale Iteration & wenn Klausel für die Unterbrechung zu überprüfen) :
private Callable<Object> getTestAllCallable() {
return new Callable<Object>() {
@Override
public Object call() {
for (int i = 0; i < inbuiltProxyPojoArrayList.size(); i++) {
if (!Thread.currentThread().isInterrupted()) {
//someWork
} else {
MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "ThreadInterrupted-Cancelling");
return null;
}
}
return null;
}
};
}
Aktivität/Fragment OnStop Implementierung (für Aufgabe & Shutdown Aufruf abzubrechen):
@Override
public void onStop() {
MyLogger.log(MyLogger.LOG_TYPE.INFO, "onStop called");
ThreadPoolManager.cancelAll();
ThreadPoolManager.shutdownExecutor();
super.onStop();
}
Update:
vorgenommene Änderungen:
Verschoben von der Nutzung Durchführbar statt aufrufbar .
Jetzt nicht Singleton für ExecutorService.
private class ThreadPoolManager { private ExecutorService executorService; private List<Future> queuedFutures; private BlockingQueue<Runnable> blockingQueue; private ThreadPoolManager() { MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "Threadpool-created(constructor)"); queuedFutures = new ArrayList<>(); blockingQueue = new LinkedBlockingDeque<>(); executorService =getNewExecutorService(); } private ExecutorService getNewExecutorService(){ return new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(), Runtime.getRuntime().availableProcessors(), 1, TimeUnit.SECONDS, blockingQueue); } private void submitItemTest(Runnable runnable) { MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "Threadpool-submitted item test"); if(executorService.isShutdown()){ executorService=getNewExecutorService(); } Future future = executorService.submit(runnable); queuedFutures.add(future); } private void submitTestAll(Runnable runnable) { MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "Threadpool-submitted test all"); if(executorService.isShutdown()){ executorService=getNewExecutorService(); } cancelAll(); Future future = executorService.submit(runnable); queuedFutures.add(future); } private void cancelAll() { MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "Cancelling all future tasks"); blockingQueue.clear(); for (Future future : queuedFutures) { if (!future.isDone()) { boolean cancelled = future.cancel(true); MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "Cancelled-" + cancelled); } } queuedFutures.clear(); } private void shutdownExecutor(){ MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "Shuttingdown threadpool"); executorService.shutdownNow(); blockingQueue.clear(); queuedFutures.clear(); } }
die Schuldigen gefunden, aber noch nicht die Lösung. Nach 2 ist die Implementierung von Runnables 1 von denen funktioniert (isInterrupted gibt true zurück oder kommt InterupptedException und als Task beendet), aber nicht andere.
Arbeits Runnable (Ich habe es für die Prüfung):
new Runnable() {
@Override
public void run() {
int i=0;
while(!Thread.currentThread().isInterrupted()){
try {
System.out.println(i);
Thread.currentThread().sleep(2000);
} catch (InterruptedException e) {
MyLogger.log(MyLogger.LOG_TYPE.DEBUG,"Interrupted");
return;
}
i++;
}
}
}
Problem (Ist-Code i verwenden möchten):
new Runnable(){
@Override
public void run() {
for (int i = 0; i < inbuiltProxyPojoArrayList.size(); i++) {
if (!Thread.currentThread().isInterrupted()) {
} else {
MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "Thread Interrupted (Cancelled)");
break;
}
}
}
};
Und 1 wahrscheinliche Lösung wäre Variable zu verwenden (boolean) als eine Unterbrechungsflagge innerhalb des runnable, die ich als ein letzter Ausweg betrachten werde, aber glücklich wäre, den Fehler kennen zu lernen.
Entschuldigung, ich habe meinen Code jetzt geändert, um zu enthalten, was Sie gesagt haben, tatsächlich tat ich das bereits, wie in der Problembeschreibung angegeben, wurde aber zusammen mit anderem Code gelöscht, der nicht relevant war. –
Und das löst Ihr Problem nicht? – zuckermanori
Ich war aufrufbar statt mit Runnable mit dem Gedanken zu Future-Objekt zu erhalten, während die auf ExecutorService abrufbar und nun wissen, kann auch mit Runnable getan werden. Danke, dass Sie das sagen, ich werde den Code ändern, um runnable zu verwenden. –