I wrote an android app for killing background running processes which is performed in a background thread. And I use below class to create my own simple thread framework.
public final class ThreadPool {
private static final ExecutorService sES = Executors.newCachedThreadPool();
public static Future<?> runNow(Runnable task) {
return sES.submit(task);
}
}
However, a serious problem occured. That is the exception(unchecked exception) would be consumed by Executor framework quitely. So I don't know why the ActivityManager.killBackgroundProcesses()
method does not work. After spending 2 or 3 hours and I wrote some log at almost every method invoke point, I found this method requires android.permission.KILL_BACKGROUND_PROCESSES permission, otherwise, it would throw a SecurityException that is an unchecked exception. The key is this exception is consumed by Excecutor framework, so I cannot see any exception information at logcat and the app does not crash at all and runs weird.
Of course, I don't know that at first, so I spent a lot of time to find out that reason, mainly depending on two posts:
Handling exceptions from Java ExecutorService tasks and
Catching thread exceptions from Java ExecutorService
So I changed the my ThreadPool class as:
public final class ThreadPool {
private static final ExecutorService sES = Executors.newCachedThreadPool();
/*
* submit(Runnable) and execute(Runnable) method has
* big difference. Especially in Exception handling!!!
* You have to pay attention.
*/
public static Future<?> submitNow(Runnable task) {
return sES.submit(task);
}
public static void executeNow(Runnable task) {
sES.execute(task);
}
}
But I still have below question:
- Why Sun/Oracle decide to consume the exception instead of transfer to users to handle if submit(Runnable command) method is used?
- How can I change this behavior to handle unchecked exception according to my own need if I insist using submit() method?
And my doubts are:
- If submit(Runnable command) method is used, I know the exception result can be get by
Future.get()
method. But, if we use Future.get() method to judge if an exception occured, the thread Future object located in would be block. That is not what we expect in most case, I suppose. - I also learned
Executor.execute()
method handles exception like common Thread.start(). But there is no return value. So the task cannot be shut down at any time. Users have no ability to shut down any running thread byFuture.cancel()
method when leaving activity.