
1. preface
The first two articles briefly analyzed Future interfaceand FutureTask this article will introduce FutureTask
Use method.
2. Use of FutureTask
FutureTask
There are two constructors, each passing in Runnale
and Callable
Examples. so FutureTask
The use of is related to these two interfaces.
2.1 Combine Callable
Callable
The interface only defines one call()
Methods, andRunnable
therun()
Method, which has a return value, genericV
This is the type of result to be returned, and the execution results of subtasks can be returned. If you want to get the results of thread execution, use the Callable
, and Callable
Exceptions can be thrown. We define a simple task:
package cn.felord;
import java.util.concurrent.Callable;
/**
* @author felord.cn
* @since 2020/3/21 20:35
*/
public class MyTask implements Callable<Integer> {
@Override
public Integer call() {
int total = 0;
try {
for (int i = 0; i < 10; i++) {
System.out.println(" thread: " + Thread.currentThread().getName() + " i = " + i);
Thread.sleep(1000);
total += i;
}
} catch (InterruptedException e) {
System.out.println("task is interrupted");
//An exception is encountered and an interrupt is required to return to ensure that the thread is terminated
return 0;
}
return total;
}
}
And then below is in a main
Template steps in the method:
public static void main(String[] args) {
//Step 1: Declare specific computing tasks
MyTask myTask = new MyTask();
//Step 2: Transfer the task to the initialization FutureTask
FutureTask<Integer> futureTask = new FutureTask<>(myTask);
//Step 3: Hand over FutureTask to a thread to execute
Thread thread = new Thread(futureTask);
thread.setName("future task thread");
thread.start();
try {
Integer integer = futureTask.get();
System.out.println("integer = " + integer);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
System.out.println(" task is over ");
}
After running, it seems to return expected values 45
, there seems to be no problem. But when we use the timeout mechanism, which is to change the code to get the result in the above code to laterInteger integer = futureTask.get(5000, TimeUnit.MILLISECONDS);
The results were as follows:
thread: future task thread i = 0
thread: future task thread i = 1
thread: future task thread i = 2
thread: future task thread i = 3
thread: future task thread i = 4
java.util.concurrent.TimeoutException
at java.util.concurrent.FutureTask.get(FutureTask.java:205)
at cn.felord.Test.main(Test.java:26)
thread: future task thread i = 5
task is over
thread: future task thread i = 6
thread: future task thread i = 7
thread: future task thread i = 8
thread: future task thread i = 9
We force the task to timeout, but the task's calculation thread is still calculating, so we need to handle the timeout exception or interrupt the calculation or continue get
。
A timeout for getting FutureTask results does not mean the end of the task. Moreover, it is usually not recommended to use the above methods for task calculation.
2.2 Combine Runnable and define the result
The structure is like this:
public FutureTask(Runnable runnable, V result) {
this.callable = Executors.callable(runnable, result);
this.state = NEW; // ensure visibility of callable
}
At first I thought this result
through runnable
Calculated, but I was wrong:
static final class RunnableAdapter<T> implements Callable<T> {
final Runnable task;
final T result;
RunnableAdapter(Runnable task, T result) {
this.task = task;
this.result = result;
}
public T call() {
task.run();
return result;
}
}
this is Executors.callable
At the bottom of the method, we cannot operate on it in threaded calculations result
。t quite understand JDK Why provide this "natural and egg" method. Run the given task and returngiven(is the parameter result you pass in, which means that the execution of the task has nothing to do with the given result.
2.3 Used with thread pool
We only use the above two methods in our research, and it is recommended to use a specific thread pool for general operating threads. Therefore, the following methods are orthodox use FutureTask
Methods:
package cn.felord;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author dax
* @since 2020/3/21 20:49
*/
public class Test {
public static void main(String[] args) {
//Step 1: Declare specific computing tasks
MyTask myTask = new MyTask();
//Step 2: Hand FutureTask to the thread pool for execution
// ExecutorService pool = Executors.newCachedThreadPool();
//It is generally recommended to use a custom thread pool or the thread pool provided by Spring to prevent OOM. The thread pool closure strategy should also be considered
ExecutorService pool = newThreadPool();
try {
//Get results
Integer integer = pool.submit(myTask).get();
System.out.println("integer = " + integer);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
private static ExecutorService newThreadPool() {
ThreadFactory namedThreadFactory = new ThreadFactory() {
final AtomicInteger sequence = new AtomicInteger(1);
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
int seq = this.sequence.getAndIncrement();
thread.setName("future-task-thread" + (seq > 1 ? "-" + seq : ""));
if (! thread.isDaemon()) {
thread.setDaemon(true);
}
return thread;
}
};
return new ThreadPoolExecutor(5, 200,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(1024),
namedThreadFactory,
new ThreadPoolExecutor.AbortPolicy());
}
}
Is this method safer and simpler?
3. the problems
-
if a particular
Callable
anomalies were try-catch Be sure to return a result, otherwise the thread will continue execution. -
call
get()
Method blocks until the task has completed execution and does not return. -
get(long timeout, TimeUnit unit)
Used to obtain execution results within a certain time. If it times out, subsequent code will continue to execute, and the calculation will not be interrupted. -
cancel(boolean mayInterruptIfRunning)
The task may not be interrupted immediately, but you need to call theisDone
orisCancelled
Judging, it is safer to call the task thread'sisInterrupted()
Conduct interrupt status judgment.
4. summary
today FutureTask
It lists the usage methods of, and also explains some misunderstandings that are easy to occur in use, hoping to help you. If you have any questions, you can leave a message to discuss it.
Comments0