Listening to multithreading timeout: Future

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 him
get it~




Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324774484&siteId=291194637