As we all know, multithreading is a good thing. Reasonable use of multithreading can improve resource utilization and shorten the processing time of large batches of tasks. Of course, while being efficient, there are also problems. This article will introduce some processing methods for thread timeout, hoping to help beginners ^_^
Scenes
1. The thread accidentally fell into an infinite loop in a while or somewhere (if not accidentally, please fix the logic error first)
2. The thread executes a time-consuming task, and I hope to end the thread within a limited time regardless of whether the execution is finished or not.
Solution
java.util.concurrent.Future
Take a look at the introduction to this interface in the documentation
Translate this sentence:
The result of the first sentence of asynchronous calculation, it sounds like this (of course, the following sentence is wrong)
Future task = new MyThread().run();
After getting this result, we can use get() to get the execution result of the thread
String result = task.get();
You can use get(time, unit) to get the execution result of the thread and monitor the timeout
String result = task.get(1000, TimeUnit.MILLISECONDS);
Can use cancel() to cancel the task
task.cancel();
and some other methods
boolean isDone = task.isDone(); boolean isCancelled = task.isCancelled();
Let's start writing code.
Monitor single thread timeout
public class TestThread implements Callable<String> { @Override public String call() { System.out.println(System.currentTimeMillis() + "come in" + this.hashCode()); try { Thread.sleep(5000); } catch (InterruptedException e) {} return System.currentTimeMillis() + "Come out" + this.hashCode(); } public static void main(String[] args) { FutureTask<String> task = new FutureTask<String>(new TestThread()); new Thread(task).start(); try { //3000 is the timeout String result = task.get(3000, TimeUnit.MILLISECONDS); System.out.println(result); } catch (InterruptedException e) { System.out.println("Thread has stopped"); } catch (ExecutionException e) { } catch (TimeoutException e) { System.out.println(System.currentTimeMillis() + "The thread timed out, kill him"); task.cancel(true); } } }
Let's take a look at the console output
1524559858691 came in 1893883033 1524559861691 thread timed out, kill him
Yes, it is very simple to achieve. But in fact, there is a big hole here. I believe you have noticed the title I wrote above: Monitoring single thread timeout -_- because the get method is blocking .
if you write
FutureTask<String> task = new FutureTask<String>(new TestThread()); FutureTask<String> task2 = new FutureTask<String>(new TestThread()); new Thread(task).start(); new Thread(task2).start(); try { String result = task.get(3000, TimeUnit.MILLISECONDS); System.out.println(result); } catch (InterruptedException | ExecutionException e) { } catch (TimeoutException e) { System.out.println(System.currentTimeMillis() + "The thread timed out, kill him"); task.cancel(true); } try { String result = task2.get(3000, TimeUnit.MILLISECONDS); System.out.println(result); } catch (InterruptedException | ExecutionException e) { } catch (TimeoutException e) { System.out.println(System.currentTimeMillis() + "The thread timed out, kill him"); task.cancel(true); }
Look at the results, thread 1 was killed, and thread 2 was at large
1524559903444 came in 1584403035 1524559903444 came in 1893883033 1524559906444 thread timed out, kill him 1524559908444 came out 1893883033
Monitor multithreading timeout
Remember the phrase "and some other methods" in the paragraph introducing the api?
Main class:
public class Main implements Runnable { //Thread Pool public static final ExecutorService pool = Executors.newFixedThreadPool(3); @Override public void run() { FutureTask<String> task = new FutureTask<String>(new TestThread()); new Thread(task).start(); long start = System.currentTimeMillis(); while (!task.isDone()) { long now = System.currentTimeMillis(); if ((now - start) >= 3000) {//Timeout 3000 milliseconds task.cancel(true); System.out.println(System.currentTimeMillis() + "The thread timed out, kill him"); } } } public static void main(String[] args) { for (int i = 0; i < 3; i++) { pool.execute(new Main()); } } }
Thread class:
public class TestThread implements Callable<String> { public static final ExecutorService pool = Executors.newFixedThreadPool(5); @Override public String call() { System.out.println(System.currentTimeMillis() + "come in" + this.hashCode()); try { Thread.sleep(5000); } catch (InterruptedException e) {} return System.currentTimeMillis() + "Come out" + this.hashCode(); } }
Let's take a look at the execution result of the main method of the Main class
1524561058283 came in 1966105457 1524561058283 came in 227309514 1524561058283 came in 120056986 1524561061283 thread timed out, kill him 1524561061283 thread timed out, kill him 1524561061283 thread timed out, kill himget it~