在 Android 应用程序的 UI 线程中,我需要运行一个可能需要纳秒或永远完成的方法。我想我无法准确确定它何时会永远持续下去,因此我通过池在单独的线程中运行它。
myPool = Executors.newCachedThreadPool(new ThreadFactory(){
//override newThread(Runnable r)...
});
Future<Result> futureResult = myPool.submit(new Callable<Result>(){
@Override public Result call(){
return dangerousMethod();
}
});
出于演示目的,我将 UI 阻塞一秒钟,然后,如果该方法尚未完成,我将继续。
try{
Result result = futureResult.get(1, TimeUnit.SECONDS);
//Use result here
}catch(TimeoutException e) {//Other Exceptions are ommited
futureResult.cancel(true);
Log.d("DEMO", "Method takes too long. Skip");
}
我尝试取消 future 并使用 futureResult.cancel(true)
中断其线程,但 dangerousMethod()
不会响应中断,因此线程将继续运行,直到最终完成其任务。
我尝试过的方法:子类化ThreadPoolExecutor
并通过反射(ThreadPoolExecutor$Worker.thread
)获取私有(private)Thread
,以强制(不良实践TM)stop()
(因为UnsupportedOperationException
而不起作用)或stop0()
(也因为NoSuch而不起作用)方法异常
)。有关此的更多详细信息:
class MyPool extends ThreadPoolExecutor{
//constructor, reflection code to get the Threads, etc
void cancelThread(Thread thread){
try {
thread.stop();
}catch(SecurityException | UnsupportedOperationException e) {
try {
Method stopMethod = Thread.class.getDeclaredMethod("stop0", Object.class);
stopMethod.setAccessible(true);
stopMethod.invoke(thread, new ThreadDeath());
}catch(NoSuchMethodException |
InvocationTargetException |
IllegalAccessException x)
{
Log.d("MyPool", "Can't stop thread", x);
}
}
}
}
危险的方法其实是这样的:
BigDecimal n1 = new BigDecimal("1E1000000");
BigDecimal n2 = new BigDecimal("1");
BigDecimal result = n1.add(n2);//Takes too long
我可以检查我使用的每个 BigDecimal 方法是否可以很好地处理数字,但我首先想知道我是否遗漏了一些明显的东西或者还有其他方法。因为
BigDecimal n3 = new BigDecimal("1E999999");
BigDecimal result = n1.add(n3);
效果很好。
最佳答案
似乎你无法在 Android 中强行终止 Java 线程 - 在 Oracle Java 中它实际上仍然有效。原因是在 Oracle Java 中 stop()
调用 stop1()
,而在 Android 上它调用 stop(new ThreadDeath())
,后者又无条件抛出 UnsupportedOperationException
。
但是为什么要强制它停止呢?只需让它在后台运行,忘记它并继续。当然,您存在内存和 CPU 陷入困境的风险,但正如您所说,只有某些数字会导致该方法运行那么长时间,因此您很可能会忘记这个线程,并能够成功启动大多数其他线程。
如果长时间运行的后台线程在完成后尝试执行操作,您可以设置一个标志告诉他闭嘴。只要您不需要它的结果,您就可以了。
关于java - java/android 线程中长的、不可中断的方法的替代方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45464592/