如何包装方法,以便在超过指定的超时时可以终止执行?

时间:2022-01-29 07:01:41

I have a method that I would like to call. However, I'm looking for a clean, simple way to kill it or force it to return if it is taking too long to execute.

我有一个方法,我想打电话。但是,我正在寻找一种干净,简单的方法来杀死它或强迫它返回,如果执行时间太长。

I'm using Java.

我正在使用Java。

to illustrate:

logger.info("sequentially executing all batches...");
for (TestExecutor executor : builder.getExecutors()) {
logger.info("executing batch...");
executor.execute();
}

I figure the TestExecutor class should implement Callable and continue in that direction.

我认为TestExecutor类应该实现Callable并继续朝这个方向发展。

But all i want to be able to do is stop executor.execute() if it's taking too long.

但我想要做的就是停止executor.execute(),如果它花了太长时间。

Suggestions...?

EDIT

Many of the suggestions received assume that the method being executed that takes a long time contains some kind of loop and that a variable could periodically be checked. However, this is not the case. So something that won't necessarily be clean and that will just stop the execution whereever it is is acceptable.

收到的许多建议都假设正在执行的方法需要很长时间才能包含某种循环,并且可以定期检查变量。然而,这种情况并非如此。因此,某些东西不一定是干净的,只会停止执行,这是可以接受的。

7 个解决方案

#1


11  

You should take a look at these classes : FutureTask, Callable, Executors

您应该看一下这些类:FutureTask,Callable,Executors

Here is an example :

这是一个例子:

public class TimeoutExample {
    public static Object myMethod() {
        // does your thing and taking a long time to execute
        return someResult;
    }

    public static void main(final String[] args) {
        Callable<Object> callable = new Callable<Object>() {
            public Object call() throws Exception {
                return myMethod();
            }
        };
        ExecutorService executorService = Executors.newCachedThreadPool();

        Future<Object> task = executorService.submit(callable);
        try {
            // ok, wait for 30 seconds max
            Object result = task.get(30, TimeUnit.SECONDS);
            System.out.println("Finished with result: " + result);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        } catch (TimeoutException e) {
            System.out.println("timeout...");
        } catch (InterruptedException e) {
            System.out.println("interrupted");
        }
    }
}

#2


8  

Java's interruption mechanism is intended for this kind of scenario. If the method that you wish to abort is executing a loop, just have it check the thread's interrupted status on every iteration. If it's interrupted, throw an InterruptedException.

Java的中断机制适用于这种情况。如果您希望中止的方法是执行循环,只需让它在每次迭代时检查线程的中断状态。如果它被中断,则抛出InterruptedException。

Then, when you want to abort, you just have to invoke interrupt on the appropriate thread.

然后,当你想要中止时,你只需要在适当的线程上调用中断。

Alternatively, you can use the approach Sun suggest as an alternative to the deprecated stop method. This doesn't involve throwing any exceptions, the method would just return normally.

或者,您可以使用Sun建议的方法替代已弃用的停止方法。这不涉及抛出任何异常,该方法只会正常返回。

#3


7  

I'm assuming the use of multiple threads in the following statements.

我假设在以下语句中使用多个线程。

I've done some reading in this area and most authors say that it's a bad idea to kill another thread.

我已经在这个领域做了一些阅读,大多数作者说杀死另一个线程是个坏主意。

If the function that you want to kill can be designed to periodically check a variable or synchronization primitive, and then terminate cleanly if that variable or synchronization primitive is set, that would be pretty clean. Then some sort of monitor thread can sleep for a number of milliseconds and then set the variable or synchronization primitive.

如果要杀死的函数可以设计为定期检查变量或同步原语,然后在设置该变量或同步原语时干净地终止,那将非常干净。然后某种监视器线程可以休眠几毫秒,然后设置变量或同步原语。

#4


3  

Really, you can't... The only way to do it is to either use thread.stop, agree on a 'cooperative' method (e.g. occassionally check for Thread.isInterrupted or call a method which throws an InterruptedException, e.g. Thread.sleep()), or somehow invoke the method in another JVM entirely.

真的,你不能......唯一的方法是使用thread.stop,同意一个'合作'方法(例如,偶尔检查Thread.isInterrupted或调用抛出InterruptedException的方法,例如Thread。 sleep()),或以某种方式完全调用另一个JVM中的方法。

For certain kinds of tests, calling stop() is okay, but it will probably damage the state of your test suite, so you'll have to relaunch the JVM after each call to stop() if you want to avoid interaction effects.

对于某些类型的测试,调用stop()是可以的,但它可能会损坏测试套件的状态,所以如果你想避免交互影响,你必须在每次调用stop()之后重新启动JVM。

For a good description of how to implement the cooperative approach, check out Sun's FAQ on the deprecated Thread methods.

有关如何实现协作方法的详细说明,请查看Sun关于弃用的Thread方法的常见问题解答。

For an example of this approach in real life, Eclipse RCP's Job API's 'IProgressMonitor' object allows some management service to signal sub-processes (via the 'cancel' method) that they should stop. Of course, that relies on the methods to actually check the isCancelled method regularly, which they often fail to do.

对于现实生活中这种方法的一个例子,Eclipse RCP的Job API的'IProgressMonitor'对象允许一些管理服务通知它们应该停止的子进程(通过'cancel'方法)。当然,这依赖于定期实际检查isCancelled方法的方法,而这些方法通常无法做到。

A hybrid approach might be to ask the thread nicely with interrupt, then insist a couple of seconds later with stop. Again, you shouldn't use stop in production code, but it might be fine in this case, esp. if you exit the JVM soon after.

混合方法可能是通过中断很好地询问线程,然后在几秒钟之后坚持停止。同样,你不应该在生产代码中使用stop,但在这种情况下它可能没问题,尤其是。如果你很快退出JVM。

To test this approach, I wrote a simple harness, which takes a runnable and tries to execute it. Feel free to comment/edit.

为了测试这种方法,我编写了一个简单的线束,它使用runnable并尝试执行它。随意评论/编辑。

public void testStop(Runnable r) {
    Thread t = new Thread(r);
    t.start();
    try {
        t.join(2000);
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }

    if (!t.isAlive()) {
        System.err.println("Finished on time.");
        return;
    }

    try {
        t.interrupt();
        t.join(2000);
        if (!t.isAlive()) {
            System.err.println("cooperative stop");
            return;
        }
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
    System.err.println("non-cooperative stop");
    StackTraceElement[] trace = Thread.getAllStackTraces().get(t);
    if (null != trace) {
        Throwable temp = new Throwable();
        temp.setStackTrace(trace);
        temp.printStackTrace();
    }
    t.stop();
    System.err.println("stopped non-cooperative thread");
}

To test it, I wrote two competing infinite loops, one cooperative, and one that never checks its thread's interrupted bit.

为了测试它,我写了两个竞争的无限循环,一个合作,一个永远不会检查其线程的中断位。

public void cooperative() {
    try {
        for (;;) {
            Thread.sleep(500);
        }
    } catch (InterruptedException e) {
        System.err.println("cooperative() interrupted");
    } finally {
        System.err.println("cooperative() finally");
    }
}

public void noncooperative() {
    try {
        for (;;) {
            Thread.yield();
        }
    } finally {
        System.err.println("noncooperative() finally");
    }
}

Finally, I wrote the tests (JUnit 4) to exercise them:

最后,我编写了测试(JUnit 4)来练习它们:

@Test
public void testStopCooperative() {
    testStop(new Runnable() {
        @Override
        public void run() {
            cooperative();
        }
    });
}

@Test
public void testStopNoncooperative() {
    testStop(new Runnable() {
        @Override
        public void run() {
            noncooperative();
        }
    });
}

I had never used Thread.stop() before, so I was unaware of its operation. It works by throwing a ThreadDeath object from whereever the target thread is currently running. This extends Error. So, while it doesn't always work cleanly, it will usually leave simple programs with a fairly reasonable program state. For example, any finally blocks are called. If you wanted to be a real jerk, you could catch ThreadDeath (or Error), and keep running, anyway!

我之前从未使用过Thread.stop(),所以我没有意识到它的操作。它的工作原理是从目标线程当前运行的东西中抛出一个ThreadDeath对象。这扩展了错误。因此,虽然它并不总是干净利落,但它通常会使程序状态相当合理的简单程序。例如,调用任何finally块。如果你想成为一个真正的混蛋,你可以抓住ThreadDeath(或错误),并继续运行!

If nothing else, this really makes me wish more code followed the IProgressMonitor approach - adding another parameter to methods that might take a while, and encouraging the implementor of the method to occasionally poll the Monitor object to see if the user wants the system to give up. I'll try to follow this pattern in the future, especially methods that might be interactive. Of course, you don't necessarily know in advance which methods will be used this way, but that is what Profilers are for, I guess.

如果没有别的,这真的让我希望更多的代码遵循IProgressMonitor方法 - 向可能需要一段时间的方法添加另一个参数,并鼓励方法的实现者偶尔轮询Monitor对象以查看用户是否希望系统给出起来。我将来会尝试遵循这种模式,特别是可能是交互式的方法。当然,你不一定事先知道哪种方法会以这种方式使用,但我认为这就是Profilers的用途。

As for the 'start another JVM entirely' method, that will take more work. I don't know if anyone has written a delegating class loader, or if one is included in the JVM, but that would be required for this approach.

至于'开始另一个JVM完全'的方法,这将需要更多的工作。我不知道是否有人编写了委托类加载器,或者是否包含在JVM中,但这种方法需要这样做。

#5


1  

Nobody answered it directly, so here's the closest thing i can give you in a short amount of psuedo code:

没有人直接回答,所以这是我能用短暂的伪代码给你的最接近的东西:

wrap the method in a runnable/callable. The method itself is going to have to check for interrupted status if you want it to stop (for example, if this method is a loop, inside the loop check for Thread.currentThread().isInterrupted and if so, stop the loop (don't check on every iteration though, or you'll just slow stuff down. in the wrapping method, use thread.join(timeout) to wait the time you want to let the method run. or, inside a loop there, call join repeatedly with a smaller timeout if you need to do other things while waiting. if the method doesn't finish, after joining, use the above recommendations for aborting fast/clean.

将方法包装在runnable / callable中。如果你想让它停止,方法本身就必须检查中断状态(例如,如果这个方法是循环,在循环内检查Thread.currentThread()。isInterrupted,如果是,则停止循环(don但是,检查每次迭代,或者你只是放慢速度。在包装方法中,使用thread.join(timeout)等待你想让方法运行的时间。或者在循环内部,调用join如果你需要在等待时做其他事情,则反复使用较小的超时。如果方法没有完成,在加入后,使用上述建议中止快速/清除。

so code wise, old code:

所以代码明智,旧代码:

void myMethod()
{
    methodTakingAllTheTime();
}

new code:

void myMethod()
{
    Thread t = new Thread(new Runnable()
        {
            public void run()
            {
                 methodTakingAllTheTime(); // modify the internals of this method to check for interruption
            }
        });
    t.join(5000); // 5 seconds
    t.interrupt();
}

but again, for this to work well, you'll still have to modify methodTakingAllTheTime or that thread will just continue to run after you've called interrupt.

但同样,为了使其运行良好,您仍然需要修改methodTakingAllTheTime,否则该线程将在您调用中断后继续运行。

#6


0  

The correct answer is, I believe, to create a Runnable to execute the sub-program, and run this in a separate Thread. THe Runnable may be a FutureTask, which you can run with a timeout ("get" method). If it times out, you'll get a TimeoutException, in which I suggest you

我相信,正确的答案是创建一个Runnable来执行子程序,并在一个单独的Thread中运行它。 Runnable可能是FutureTask,你可以使用超时(“get”方法)运行。如果它超时,你会得到一个TimeoutException,我建议你

  • call thread.interrupt() to attempt to end it in a semi-cooperative manner (many library calls seem to be sensitive to this, so it will probably work)
  • 调用thread.interrupt()尝试以半协作的方式结束它(许多库调用似乎对此敏感,所以它可能会工作)

  • wait a little (Thread.sleep(300))
  • 稍等一下(Thread.sleep(300))

  • and then, if the thread is still active (thread.isActive()), call thread.stop(). This is a deprecated method, but apparently the only game in town short of running a separate process with all that this entails.
  • 然后,如果线程仍处于活动状态(thread.isActive()),则调用thread.stop()。这是一种不赞成使用的方法,但显然是城里唯一一款不会运行单独进程的游戏。

In my application, where I run untrusted, uncooperative code written by my beginner students, I do the above, ensuring that the killed thread never has (write) access to any objects that survive its death. This includes the object that houses the called method, which is discarded if a timeout occurs. (I tell my students to avoid timeouts, because their agent will be disqualified.) I am unsure about memory leaks...

在我的应用程序中,我运行由初学者编写的不可信,不合作的代码,我执行上述操作,确保被杀死的线程永远不会(写)访问任何在其死亡后幸存的对象。这包括容纳被调用方法的对象,如果发生超时则将其丢弃。 (我告诉我的学生避免超时,因为他们的经纪人将被取消资格。)我不确定内存泄漏...

I distinguish between long runtimes (method terminates) and hard timeouts - the hard timeouts are longer and meant to catch the case when code does not terminate at all, as opposed to being slow.

我区分长运行时(方法终止)和硬超时 - 硬超时更长,并且意味着在代码根本不终止时捕获这种情况,而不是缓慢。

From my research, Java does not seem to have a non-deprecated provision for running non-cooperative code, which, in a way, is a gaping hole in the security model. Either I can run foreign code and control the permissions it has (SecurityManager), or I cannot run foreign code, because it might end up taking up a whole CPU with no non-deprecated means to stop it.

根据我的研究,Java似乎没有一个非弃用的运行非合作代码的规定,这在某种程度上是安全模型中的一个漏洞。要么我可以运行外部代码并控制它拥有的权限(SecurityManager),要么我无法运行外部代码,因为它可能最终占用整个CPU而没有不弃用的方法来阻止它。

double x = 2.0;  
while(true) {x = x*x}; // do not terminate
System.out.print(x); // prevent optimization

#7


0  

I can think of a not so great way to do this. If you can detect when it is taking too much time, you can have the method check for a boolean in every step. Have the program change the value of the boolean tooMuchTime to true if it is taking too much time (I can't help with this). Then use something like this:

我可以想到一个不太好的方法来做到这一点。如果您可以检测何时花费太多时间,则可以让方法在每个步骤中检查布尔值。如果程序占用太多时间,程序会将boolean tooMuchTime的值更改为true(我无法帮助解决此问题)。然后使用这样的东西:

 Method(){
 //task1
if (tooMuchTime == true) return;
 //task2
if (tooMuchTime == true) return;
 //task3
if (tooMuchTime == true) return;
//task4
if (tooMuchTime == true) return;
//task5
if (tooMuchTime == true) return;
//final task
  }

#1


11  

You should take a look at these classes : FutureTask, Callable, Executors

您应该看一下这些类:FutureTask,Callable,Executors

Here is an example :

这是一个例子:

public class TimeoutExample {
    public static Object myMethod() {
        // does your thing and taking a long time to execute
        return someResult;
    }

    public static void main(final String[] args) {
        Callable<Object> callable = new Callable<Object>() {
            public Object call() throws Exception {
                return myMethod();
            }
        };
        ExecutorService executorService = Executors.newCachedThreadPool();

        Future<Object> task = executorService.submit(callable);
        try {
            // ok, wait for 30 seconds max
            Object result = task.get(30, TimeUnit.SECONDS);
            System.out.println("Finished with result: " + result);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        } catch (TimeoutException e) {
            System.out.println("timeout...");
        } catch (InterruptedException e) {
            System.out.println("interrupted");
        }
    }
}

#2


8  

Java's interruption mechanism is intended for this kind of scenario. If the method that you wish to abort is executing a loop, just have it check the thread's interrupted status on every iteration. If it's interrupted, throw an InterruptedException.

Java的中断机制适用于这种情况。如果您希望中止的方法是执行循环,只需让它在每次迭代时检查线程的中断状态。如果它被中断,则抛出InterruptedException。

Then, when you want to abort, you just have to invoke interrupt on the appropriate thread.

然后,当你想要中止时,你只需要在适当的线程上调用中断。

Alternatively, you can use the approach Sun suggest as an alternative to the deprecated stop method. This doesn't involve throwing any exceptions, the method would just return normally.

或者,您可以使用Sun建议的方法替代已弃用的停止方法。这不涉及抛出任何异常,该方法只会正常返回。

#3


7  

I'm assuming the use of multiple threads in the following statements.

我假设在以下语句中使用多个线程。

I've done some reading in this area and most authors say that it's a bad idea to kill another thread.

我已经在这个领域做了一些阅读,大多数作者说杀死另一个线程是个坏主意。

If the function that you want to kill can be designed to periodically check a variable or synchronization primitive, and then terminate cleanly if that variable or synchronization primitive is set, that would be pretty clean. Then some sort of monitor thread can sleep for a number of milliseconds and then set the variable or synchronization primitive.

如果要杀死的函数可以设计为定期检查变量或同步原语,然后在设置该变量或同步原语时干净地终止,那将非常干净。然后某种监视器线程可以休眠几毫秒,然后设置变量或同步原语。

#4


3  

Really, you can't... The only way to do it is to either use thread.stop, agree on a 'cooperative' method (e.g. occassionally check for Thread.isInterrupted or call a method which throws an InterruptedException, e.g. Thread.sleep()), or somehow invoke the method in another JVM entirely.

真的,你不能......唯一的方法是使用thread.stop,同意一个'合作'方法(例如,偶尔检查Thread.isInterrupted或调用抛出InterruptedException的方法,例如Thread。 sleep()),或以某种方式完全调用另一个JVM中的方法。

For certain kinds of tests, calling stop() is okay, but it will probably damage the state of your test suite, so you'll have to relaunch the JVM after each call to stop() if you want to avoid interaction effects.

对于某些类型的测试,调用stop()是可以的,但它可能会损坏测试套件的状态,所以如果你想避免交互影响,你必须在每次调用stop()之后重新启动JVM。

For a good description of how to implement the cooperative approach, check out Sun's FAQ on the deprecated Thread methods.

有关如何实现协作方法的详细说明,请查看Sun关于弃用的Thread方法的常见问题解答。

For an example of this approach in real life, Eclipse RCP's Job API's 'IProgressMonitor' object allows some management service to signal sub-processes (via the 'cancel' method) that they should stop. Of course, that relies on the methods to actually check the isCancelled method regularly, which they often fail to do.

对于现实生活中这种方法的一个例子,Eclipse RCP的Job API的'IProgressMonitor'对象允许一些管理服务通知它们应该停止的子进程(通过'cancel'方法)。当然,这依赖于定期实际检查isCancelled方法的方法,而这些方法通常无法做到。

A hybrid approach might be to ask the thread nicely with interrupt, then insist a couple of seconds later with stop. Again, you shouldn't use stop in production code, but it might be fine in this case, esp. if you exit the JVM soon after.

混合方法可能是通过中断很好地询问线程,然后在几秒钟之后坚持停止。同样,你不应该在生产代码中使用stop,但在这种情况下它可能没问题,尤其是。如果你很快退出JVM。

To test this approach, I wrote a simple harness, which takes a runnable and tries to execute it. Feel free to comment/edit.

为了测试这种方法,我编写了一个简单的线束,它使用runnable并尝试执行它。随意评论/编辑。

public void testStop(Runnable r) {
    Thread t = new Thread(r);
    t.start();
    try {
        t.join(2000);
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }

    if (!t.isAlive()) {
        System.err.println("Finished on time.");
        return;
    }

    try {
        t.interrupt();
        t.join(2000);
        if (!t.isAlive()) {
            System.err.println("cooperative stop");
            return;
        }
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
    System.err.println("non-cooperative stop");
    StackTraceElement[] trace = Thread.getAllStackTraces().get(t);
    if (null != trace) {
        Throwable temp = new Throwable();
        temp.setStackTrace(trace);
        temp.printStackTrace();
    }
    t.stop();
    System.err.println("stopped non-cooperative thread");
}

To test it, I wrote two competing infinite loops, one cooperative, and one that never checks its thread's interrupted bit.

为了测试它,我写了两个竞争的无限循环,一个合作,一个永远不会检查其线程的中断位。

public void cooperative() {
    try {
        for (;;) {
            Thread.sleep(500);
        }
    } catch (InterruptedException e) {
        System.err.println("cooperative() interrupted");
    } finally {
        System.err.println("cooperative() finally");
    }
}

public void noncooperative() {
    try {
        for (;;) {
            Thread.yield();
        }
    } finally {
        System.err.println("noncooperative() finally");
    }
}

Finally, I wrote the tests (JUnit 4) to exercise them:

最后,我编写了测试(JUnit 4)来练习它们:

@Test
public void testStopCooperative() {
    testStop(new Runnable() {
        @Override
        public void run() {
            cooperative();
        }
    });
}

@Test
public void testStopNoncooperative() {
    testStop(new Runnable() {
        @Override
        public void run() {
            noncooperative();
        }
    });
}

I had never used Thread.stop() before, so I was unaware of its operation. It works by throwing a ThreadDeath object from whereever the target thread is currently running. This extends Error. So, while it doesn't always work cleanly, it will usually leave simple programs with a fairly reasonable program state. For example, any finally blocks are called. If you wanted to be a real jerk, you could catch ThreadDeath (or Error), and keep running, anyway!

我之前从未使用过Thread.stop(),所以我没有意识到它的操作。它的工作原理是从目标线程当前运行的东西中抛出一个ThreadDeath对象。这扩展了错误。因此,虽然它并不总是干净利落,但它通常会使程序状态相当合理的简单程序。例如,调用任何finally块。如果你想成为一个真正的混蛋,你可以抓住ThreadDeath(或错误),并继续运行!

If nothing else, this really makes me wish more code followed the IProgressMonitor approach - adding another parameter to methods that might take a while, and encouraging the implementor of the method to occasionally poll the Monitor object to see if the user wants the system to give up. I'll try to follow this pattern in the future, especially methods that might be interactive. Of course, you don't necessarily know in advance which methods will be used this way, but that is what Profilers are for, I guess.

如果没有别的,这真的让我希望更多的代码遵循IProgressMonitor方法 - 向可能需要一段时间的方法添加另一个参数,并鼓励方法的实现者偶尔轮询Monitor对象以查看用户是否希望系统给出起来。我将来会尝试遵循这种模式,特别是可能是交互式的方法。当然,你不一定事先知道哪种方法会以这种方式使用,但我认为这就是Profilers的用途。

As for the 'start another JVM entirely' method, that will take more work. I don't know if anyone has written a delegating class loader, or if one is included in the JVM, but that would be required for this approach.

至于'开始另一个JVM完全'的方法,这将需要更多的工作。我不知道是否有人编写了委托类加载器,或者是否包含在JVM中,但这种方法需要这样做。

#5


1  

Nobody answered it directly, so here's the closest thing i can give you in a short amount of psuedo code:

没有人直接回答,所以这是我能用短暂的伪代码给你的最接近的东西:

wrap the method in a runnable/callable. The method itself is going to have to check for interrupted status if you want it to stop (for example, if this method is a loop, inside the loop check for Thread.currentThread().isInterrupted and if so, stop the loop (don't check on every iteration though, or you'll just slow stuff down. in the wrapping method, use thread.join(timeout) to wait the time you want to let the method run. or, inside a loop there, call join repeatedly with a smaller timeout if you need to do other things while waiting. if the method doesn't finish, after joining, use the above recommendations for aborting fast/clean.

将方法包装在runnable / callable中。如果你想让它停止,方法本身就必须检查中断状态(例如,如果这个方法是循环,在循环内检查Thread.currentThread()。isInterrupted,如果是,则停止循环(don但是,检查每次迭代,或者你只是放慢速度。在包装方法中,使用thread.join(timeout)等待你想让方法运行的时间。或者在循环内部,调用join如果你需要在等待时做其他事情,则反复使用较小的超时。如果方法没有完成,在加入后,使用上述建议中止快速/清除。

so code wise, old code:

所以代码明智,旧代码:

void myMethod()
{
    methodTakingAllTheTime();
}

new code:

void myMethod()
{
    Thread t = new Thread(new Runnable()
        {
            public void run()
            {
                 methodTakingAllTheTime(); // modify the internals of this method to check for interruption
            }
        });
    t.join(5000); // 5 seconds
    t.interrupt();
}

but again, for this to work well, you'll still have to modify methodTakingAllTheTime or that thread will just continue to run after you've called interrupt.

但同样,为了使其运行良好,您仍然需要修改methodTakingAllTheTime,否则该线程将在您调用中断后继续运行。

#6


0  

The correct answer is, I believe, to create a Runnable to execute the sub-program, and run this in a separate Thread. THe Runnable may be a FutureTask, which you can run with a timeout ("get" method). If it times out, you'll get a TimeoutException, in which I suggest you

我相信,正确的答案是创建一个Runnable来执行子程序,并在一个单独的Thread中运行它。 Runnable可能是FutureTask,你可以使用超时(“get”方法)运行。如果它超时,你会得到一个TimeoutException,我建议你

  • call thread.interrupt() to attempt to end it in a semi-cooperative manner (many library calls seem to be sensitive to this, so it will probably work)
  • 调用thread.interrupt()尝试以半协作的方式结束它(许多库调用似乎对此敏感,所以它可能会工作)

  • wait a little (Thread.sleep(300))
  • 稍等一下(Thread.sleep(300))

  • and then, if the thread is still active (thread.isActive()), call thread.stop(). This is a deprecated method, but apparently the only game in town short of running a separate process with all that this entails.
  • 然后,如果线程仍处于活动状态(thread.isActive()),则调用thread.stop()。这是一种不赞成使用的方法,但显然是城里唯一一款不会运行单独进程的游戏。

In my application, where I run untrusted, uncooperative code written by my beginner students, I do the above, ensuring that the killed thread never has (write) access to any objects that survive its death. This includes the object that houses the called method, which is discarded if a timeout occurs. (I tell my students to avoid timeouts, because their agent will be disqualified.) I am unsure about memory leaks...

在我的应用程序中,我运行由初学者编写的不可信,不合作的代码,我执行上述操作,确保被杀死的线程永远不会(写)访问任何在其死亡后幸存的对象。这包括容纳被调用方法的对象,如果发生超时则将其丢弃。 (我告诉我的学生避免超时,因为他们的经纪人将被取消资格。)我不确定内存泄漏...

I distinguish between long runtimes (method terminates) and hard timeouts - the hard timeouts are longer and meant to catch the case when code does not terminate at all, as opposed to being slow.

我区分长运行时(方法终止)和硬超时 - 硬超时更长,并且意味着在代码根本不终止时捕获这种情况,而不是缓慢。

From my research, Java does not seem to have a non-deprecated provision for running non-cooperative code, which, in a way, is a gaping hole in the security model. Either I can run foreign code and control the permissions it has (SecurityManager), or I cannot run foreign code, because it might end up taking up a whole CPU with no non-deprecated means to stop it.

根据我的研究,Java似乎没有一个非弃用的运行非合作代码的规定,这在某种程度上是安全模型中的一个漏洞。要么我可以运行外部代码并控制它拥有的权限(SecurityManager),要么我无法运行外部代码,因为它可能最终占用整个CPU而没有不弃用的方法来阻止它。

double x = 2.0;  
while(true) {x = x*x}; // do not terminate
System.out.print(x); // prevent optimization

#7


0  

I can think of a not so great way to do this. If you can detect when it is taking too much time, you can have the method check for a boolean in every step. Have the program change the value of the boolean tooMuchTime to true if it is taking too much time (I can't help with this). Then use something like this:

我可以想到一个不太好的方法来做到这一点。如果您可以检测何时花费太多时间,则可以让方法在每个步骤中检查布尔值。如果程序占用太多时间,程序会将boolean tooMuchTime的值更改为true(我无法帮助解决此问题)。然后使用这样的东西:

 Method(){
 //task1
if (tooMuchTime == true) return;
 //task2
if (tooMuchTime == true) return;
 //task3
if (tooMuchTime == true) return;
//task4
if (tooMuchTime == true) return;
//task5
if (tooMuchTime == true) return;
//final task
  }