java - java/android 线程中长的、不可中断的方法的替代方案

标签 java android multithreading bigdecimal java-threads

在 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/

相关文章:

Java Puzzler-这是什么原因?

java - 是否应该在 invalidate(l,t,r,b) 之后显式设置剪辑区域?

java - 如何同步不可修改的集合

c# - 限制线程数

java - 如何将 null 转换为 int 而不转换为整数?

java - Google Directions Api 似乎无法在 Kotlin 中运行

java - 为类(class)成员提供对另一个类(class)成员的引用

android - Viewpager Recyclerview 滚动滞后

Android 2.0 应用程序在 2.2 设备上不可用

c - 线程共享地址空间,但不共享堆栈 : Contradicting?