0

I want to create a thread to judge user code:

FutureTask<Integer> futureTask = new FutureTask(() -> run(type));  // run is a method
Thread thread = new Thread(futureTask);
thread.start();

As we all known, an infinite loop may be written in the user code, so the method run will be working all the time and the Thread thread will not stop. I want to terminate this thread after timeout duration. How can I terminate it instead of using Thread.stop because it's unsafe?

kesy
  • 13
  • 4
  • What about using a process? If you use a thread, it can be *very unsafe* because your thread and the user's thread are in the same address space. – ch271828n Dec 29 '20 at 09:39
  • I am thinking about it, because I need to change a lot of code if I using a process. – kesy Dec 30 '20 at 06:04

2 Answers2

2

The correct way to deal with a thread that needs to be stopped is to design the thread's code so that it responds appropriately to being interrupted:

  • Long computations need to occasionally check the current thread's "interrupted" flag.

  • InterruptedException should be handled appropriately.

  • The thread application code's response to the interrupt should be to gracefully stop what it is doing1 and (typically) allow the thread to terminate.

(You could also use a custom flag implemented using a volatile shared variable instead of the interrupted flag. However, that doesn't deal with interrupting wait, sleep and similar operations, and is therefore a poor substitute for interrupts.)


The unsafe way is to call the deprecated Thread.stop() method. (The javadocs explain why it is unsafe, and we don't need to repeat that here.)

The (related) Thread.stop(Throwable) method was removed in Java 11; see:


Unfortunately, there is nothing in between these two approaches for interrupting a thread.

If you cannot get your long running thread to cooperate, the safe alternative would be to run it in a separate process; e.g. using System.ProcessBuilder etcetera to run the java command. The (external) process could then be killed if it took too long. The downsides include:

  • An external process cannot access the current JVM's variables, etcetera. So you need to use a different mechanism to pass information between the parent and child processes.

  • Starting a new JVM is a lot more expensive than starting a new thread.


1 - For example, if the thread owns resources such as open files or sockets, it should release them. If it is performing an action for some other thread that will be waiting for the result, it should signal (in the appropriate way) that there will be no result. And so on.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Oh,sorry. Maybe I missed something important. Actually, the method `run` will invoke a native method written by C. This navtive method will start a new **thread** to judge the user code util it returns results. Once an infinite loop is in user code, it can not return. Can I terminate the thread in Java and make the child thread in C terminated? If yes, Can you tell me how to do it? – kesy Dec 30 '20 at 03:53
  • There is no direct solution for that. Even using `Thread.stop()` won't work because it won't kill the thread that you started in the native code. Note that killing a native thread has the same sort of problems that stopping or destroying a Java thread has; see https://stackoverflow.com/questions/2084830/kill-thread-in-pthread-library – Stephen C Dec 30 '20 at 03:59
  • The best solution to this problem is likely to be to run the user code in a separate JVM / external process. You can manage it using `Process.destroy()`. – Stephen C Dec 30 '20 at 04:10
  • Thank you, I will think about using `Process`, which may change lots of code. – kesy Dec 30 '20 at 06:07
0

Terminating thread from outside is ALWAYS unsafe and very strongly discouraged. You need to notify the thread that you want it to terminate and the thread must do it itself. That is done with method interrupt() of the class Thread. In your example it would be from the main code to call thread.interrupt() That will cause the interrupt flag to be raised in your thread. In your run method of your thread you should check for that flag (See methods interrupted() and isInterrupted() in the class Thread). Once you see that your flag is raised, break out of the loop and finish the method. That will stop your thread.

Michael Gantman
  • 7,315
  • 2
  • 19
  • 36