java - 由线程停止无限循环函数

时间:2018-05-26 12:47:50

标签: java

我的问题是:

public class Ex3_tester {

/** This class represents a basic implementation for Ex3testing file. */

public static double ENDLESS_LOOP=0.4;

public static void main(String[]args){

    Ex3 ex3=new Ex3();

    long n=33333331L;
    boolean ans=ex3.isPrime(n,1);
    System.out.println("n="+n+" isPrime "+ans);
}

/** DONOT change this function!,it must be used
 * byEx3-isPrime(long,double) */

public static boolean isPrime(long n){
    boolean ans=true;
    if(n<2)throw new RuntimeException("ERR: the parameter to the isPrime function must be >1 (got "+n+")!");
    int i=2;
    double ns=Math.sqrt(n) ;
    while(i<=ns&&ans){
        if (n%i==0)
            ans=false;
        i=i+1;
    }

    if(Math.random()<Ex3_tester.ENDLESS_LOOP)//responsible to enter the program into endless loop
        while(true);

    return ans;
}}

好的,在Ex3_tester中我有一个函数isprime,它确定数字是否为素数。正如你所看到的那样,函数有时会变成无限循环。

我需要尝试为这个函数创建一个包装器 - 如果'isprime'在某个时候之后我不需要关闭它。我尝试了一切。我的最佳代码,直到现在有时得到答案,但如果函数变成无限循环它会抛出异常,但我看到程序继续运行(我可以在Eclipse控制台中看到)。 这是我的代码,直到现在:

   package threads_task3;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;

public class Ex3 implements Callable<Boolean>{

    static long number;
    AtomicBoolean interrupt=new AtomicBoolean(false);

    public Boolean isPrime(long n, double d) {


        number=n;

        long time=(long)(d*1000);

        ExecutorService primeFunction=Executors.newSingleThreadExecutor();

        Future <Boolean> result=primeFunction.submit(this);

        try {

            Boolean finalresult= (result.get(time, TimeUnit.MILLISECONDS));

            if(finalresult!=null){

                primeFunction.shutdown();
                return finalresult;
            }

        } catch (InterruptedException | ExecutionException | TimeoutException e) {

            interrupt.set(true);
            primeFunction.shutdown();


            e.printStackTrace();
        }

        throw new RuntimeException();

    }

    @Override
    public Boolean call() throws Exception {

        while (!interrupt.get())
        return Ex3_tester.isPrime(number);

        throw new RuntimeException();
    }
}

谢谢!

2 个答案:

答案 0 :(得分:1)

要停止此功能,您别无选择,只能为其执行设置时间限制。如果执行时间超过k秒,它应该已找到结果并已返回。 Java有一个有点笨拙的多线程模型,所以这样做需要几行代码,但是它有支持:

static class PrimeWrapper implements Runnable {
    long n;
    boolean result;

    PrimeWrapper(long n){
        this.n = n;
    }

    @Override public void run() {
        result = isPrime(n);
    }
}

public static void main(String[] args) {
    long n = 7;
    PrimeWrapper isPrime = new PrimeWrapper(n);
    ExecutorService executor = Executors.newSingleThreadExecutor();
    Future future = executor.submit(isPrime);

    try {
        future.get(3, TimeUnit.SECONDS);
    } catch (Exception e) { // If future could not get() the result
        future.cancel(true);
        executor.shutdownNow();
        System.out.println("isPrime went in to an infintie loop. Exiting...");
        System.exit(-1);
    }
    future.cancel(true);
    executor.shutdownNow();
    System.out.println("Is " + n + " a prime number: " + isPrime.result);
}

最后我应该提一下,你可能永远不会自己编写像isPrime(long n)这样的代码(即使在等效时间复杂度可能无法避免的实际领域)。

答案 1 :(得分:0)

好的,谢谢你的帮助

我试过这个并且它起作用了:

package threads_task3;
public class Ex3 implements Runnable{

    static long number;
    static Boolean result=null;

    public Boolean isPrime(long n, double d) {


        number=n;

        long time=(long)(d*1000);

        Thread prime=new Thread(this);
        prime.setDaemon(true);

        long start=System.currentTimeMillis();
        prime.start();
        long end=System.currentTimeMillis();

        while( (end-start)<=time){

            if (result!=null)
                return result;

            end=System.currentTimeMillis();
        }

        throw new RuntimeException();




    }


    @Override
    public void run() {

        result=Ex3_tester.isPrime(number);

    }
}

但是,它不是最好的解决方案,因为如果我尝试将函数包装在很大的时间值中,那就说10秒它会从计算机中获取大量资源,如果有人有更好的想法或其他方式我会很高兴得到它!

谢谢!