清理Java中的线程 - java

我有一个Java方法,可以对一个输入集执行两次计算:一个估计值和一个准确答案。估算始终可以廉价且可靠的时间进行计算。准确的答案有时可以在可接受的时间内计算出来,而有时却不是(未知的先验...必须尝试一下)。

我要设置的是一个框架,如果准确的答案花费的时间太长(固定的超时时间),那么将使用预先计算的估计值。我想我会为此使用一个线程。主要的复杂之处在于,用于计算准确答案的代码依赖于外部库,因此我无法“注入”中断支持。

这里是此问题的独立测试用例,展示了我的问题:

package test;

import java.util.Random;

public class InterruptableProcess {
    public static final int TIMEOUT = 1000;

    public static void main(String[] args){
        for(int i=0; i<10; i++){
            getAnswer();
        }
    }

    public static double getAnswer(){
        long b4 = System.currentTimeMillis();
        // have an estimate pre-computed
        double estimate = Math.random();

        //try to get accurate answer
        //can take a long time
        //if longer than TIMEOUT, use estimate instead
        AccurateAnswerThread t = new AccurateAnswerThread();
        t.start();

        try{
            t.join(TIMEOUT);
        } catch(InterruptedException ie){
            ;
        }

        if(!t.isFinished()){
            System.err.println("Returning estimate: "+estimate+" in "+(System.currentTimeMillis()-b4)+" ms");
            return estimate;
        } else{
            System.err.println("Returning accurate answer: "+t.getAccurateAnswer()+" in "+(System.currentTimeMillis()-b4)+" ms");
            return t.getAccurateAnswer();
        }

    }

    public static class AccurateAnswerThread extends Thread{
        private boolean finished = false;
        private double answer = -1;

        public void run(){
            //call to external, non-modifiable code
            answer = accurateAnswer();
            finished = true;
        }

        public boolean isFinished(){
            return finished;
        }

        public double getAccurateAnswer(){
            return answer;
        }

        // not modifiable, emulate an expensive call
        // in practice, from an external library
        private double accurateAnswer(){
            Random r = new Random();
            long b4 = System.currentTimeMillis();
            long wait = r.nextInt(TIMEOUT*2);

            //don't want to use .wait() since
            //external code doesn't support interruption
            while(b4+wait>System.currentTimeMillis()){
                ;
            }
            return Math.random();
        }
    }
}

这可以正常输出...

Returning estimate: 0.21007465651836377 in 1002 ms
Returning estimate: 0.5303547292361411 in 1001 ms
Returning accurate answer: 0.008838428149438915 in 355 ms
Returning estimate: 0.7981717302567681 in 1001 ms
Returning estimate: 0.9207406241557682 in 1000 ms
Returning accurate answer: 0.0893839926072787 in 175 ms
Returning estimate: 0.7310211480220586 in 1000 ms
Returning accurate answer: 0.7296754467596422 in 530 ms
Returning estimate: 0.5880164300851529 in 1000 ms
Returning estimate: 0.38605296260291233 in 1000 ms

但是,我有一个很大的输入集(数十亿个项目)来进行分析,因此我不确定如何清理未完成的线程(我不希望它们在线程中运行)。背景)。

我知道有充分的理由不赞成使用各种破坏线程的方法。我也知道停止线程的典型方法是使用中断。但是,在这种情况下,由于run()方法将单个调用传递给外部库,因此我看不到可以使用中断。

在这种情况下如何杀死/清理线程?

参考方案

如果您对外部库了解足够,例如:

  • 从不获取任何锁;
  • 永远不会打开任何文件/网络连接;
  • 从不涉及任何I / O,甚至不涉及日志记录。
  • 那么可以使在其上使用Thread#stop是安全的。您可以尝试并进行广泛的压力测试。任何资源泄漏都应尽快显现出来。

    Java:线程池如何将线程映射到可运行对象 - java

    试图绕过Java并发问题,并且很难理解线程池,线程以及它们正在执行的可运行“任务”之间的关系。如果我创建一个有10个线程的线程池,那么我是否必须将相同的任务传递给池中的每个线程,或者池化的线程实际上只是与任务无关的“工人无人机”可用于执行任何任务?无论哪种方式,Executor / ExecutorService如何将正确的任务分配给正确的线程? 参考方案 …

    Java-搜索字符串数组中的字符串 - java

    在Java中,我们是否有任何方法可以发现特定字符串是字符串数组的一部分。我可以避免出现一个循环。例如String [] array = {"AA","BB","CC" }; string x = "BB" 我想要一个if (some condition to tell wheth…

    JAVA:字节码和二进制有什么区别? - java

    java字节代码(已编译的语言,也称为目标代码)与机器代码(当前计算机的本机代码)之间有什么区别?我读过一些书,他们将字节码称为二进制指令,但我不知道为什么。 参考方案 字节码是独立于平台的,在Windows中运行的编译器编译的字节码仍将在linux / unix / mac中运行。机器代码是特定于平台的,如果在Windows x86中编译,则它将仅在Win…

    java:继承 - java

    有哪些替代继承的方法? java大神给出的解决方案 有效的Java:偏重于继承而不是继承。 (这实际上也来自“四人帮”)。他提出的理由是,如果扩展类未明确设计为继承,则继承会引起很多不正常的副作用。例如,对super.someMethod()的任何调用都可以引导您通过未知代码的意外路径。取而代之的是,持有对本来应该扩展的类的引用,然后委托给它。这是与Eric…

    Java:BigInteger,如何通过OutputStream编写它 - java

    我想将BigInteger写入文件。做这个的最好方式是什么。当然,我想从输入流中读取(使用程序,而不是人工)。我必须使用ObjectOutputStream还是有更好的方法?目的是使用尽可能少的字节。谢谢马丁 参考方案 Java序列化(ObjectOutputStream / ObjectInputStream)是将对象序列化为八位字节序列的一种通用方法。但…