Foreword
Before we have learned two ways to create threads, one is the direct successor Thread
, another it is to implement Runnable
the interface.
These two methods have a defect: Unable to get the results after performing the task.
If you want to get a return value must be shared between variables by threads or means of communication, to implement more complex.
Therefore, Java5
it provided the start Callable
and Future
, you can get the task execution results after the task is completed by them.
Callable
First we look at Runnable
the source code
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
复制代码
It can be seen that run
the method returns a value ofvoid
The following look at Callable
the source code
@FunctionalInterface
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
复制代码
Can be seen, this is a generic interface, call()
type returned by the function is passed in a V type.
Callable
The use of the code will be given later in the presentation.
Future
Future
Class located java.util.concurrent
under the package, which is an interface.
public interface Future<V> {
boolean cancel(boolean mayInterruptIfRunning);
boolean isCancelled();
boolean isDone();
V get() throws InterruptedException, ExecutionException;
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
复制代码
In the Future
statement five interface methods, the following are sequentially explain the role of each method:
-
cancel method: to cancel the mission, if successful cancel the task is returned
true
if you cancel the task failed to returnfalse
. ParametermayInterruptIfRunning
indicates whether to allow cancel the task being performed has not been completed, and if the task has been completed, the mattermayInterruptIfRunning
istrue
stillfalse
, this method definitely returnfalse
, that is, if the cancellation has been completed task returnsfalse
; if the task being performed, ifmayInterruptIfRunning
settrue
, returnstrue
If themayInterruptIfRunning
setfalse
is returnedfalse
; if the task has not been executed, regardless ofmayInterruptIfRunning为true
what is sure to returntrue
. -
isCancelled method: Indicates whether the task was canceled successfully, if success is canceled before the task is completed normally is returned
true
. -
isDone method: Indicates whether the task has been completed, if the task is completed, it returns
true
; -
get () method: used to obtain the results, this method will produce obstruction, it will wait until the task is finished before returning;
-
get (long timeout, TimeUnit unit) used to obtain the results if the specified time, the results have not acquired, directly returns null.
That Future
provides three functions:
-
1. The decision task is completed;
-
2. can interrupt tasks;
-
3. be able to get the task execution results.
Future use
@Slf4j
public class FutureExample {
static class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
log.info("do sth in callable");
Thread.sleep(5000);
return "done";
}
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService executorService = Executors.newCachedThreadPool();
Future<String> future = executorService.submit(new MyCallable());
log.info("do sth in main");
Thread.sleep(1000);
String result = future.get();
log.info("result: {}", result);
}
}
复制代码
operation result
FutureTask
FutureTask
Located JUC
within the bag but not the AQS
subclass.
FutureTask
Implements Future
and Runnable
interface, you can get the return value of the thread.
FutureTask use
@Slf4j
public class FutureTaskExample {
public static void main(String[] args) throws InterruptedException, ExecutionException {
FutureTask<String> futureTask = new FutureTask<String>(new Callable<String>() {
@Override
public String call() throws Exception {
log.info("do sth. in callable");
Thread.sleep(5000);
return "Done";
}
});
new Thread(futureTask).start();
log.info("do sth. in main");
Thread.sleep(1000);
String result = futureTask.get();
log.info("result: {}", result);
}
}
复制代码
Operating results the same as above.
As can be seen from the example of the use FutureTask
is very convenient when you want to use when starting a thread on it.
FutureTask
Can also pass multiple parameter types, we look into its source code
/**
* Creates a {@code FutureTask} that will, upon running, execute the
* given {@code Callable}.
*
* @param callable the callable task
* @throws NullPointerException if the callable is null
*/
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
}
/**
* Creates a {@code FutureTask} that will, upon running, execute the
* given {@code Runnable}, and arrange that {@code get} will return the
* given result on successful completion.
*
* @param runnable the runnable task
* @param result the result to return on successful completion. If
* you don't need a particular result, consider using
* constructions of the form:
* {@code Future<?> f = new FutureTask<Void>(runnable, null)}
* @throws NullPointerException if the runnable is null
*/
public FutureTask(Runnable runnable, V result) {
this.callable = Executors.callable(runnable, result);
this.state = NEW; // ensure visibility of callable
}
复制代码
We can see FutureTask
can pass 入Callable
and Runnable
incoming Runnable
can also specify the return value type.
Fork / Join framework
Fork/Join 框架
It is Java7
provided a frame for performing tasks in parallel, to obtain the final result by a large plurality of smaller tasks into smaller tasks final summary results of each task.
It is mainly used in 工作窃取算法
this algorithm means a thread to steal from another task queue to execute the process shown below
Thread task uses a double-ended queue, you can only steal when stealing from the tail task. The advantage of this method is that you can take advantage of parallel computing threads, and reduces competition between threads. The disadvantage is that there is competition or, in extreme cases, such as when there is only one task queue.
Fork / Join framework has some limitations:
- Tasks can only use the fork and join operations as a synchronization mechanism, if other synchronization mechanism, you can not perform other tasks while working thread.
- IO operations task should not be performed
- Tasks can not throw checked exceptions, they must be handled by the necessary code.
Coding demo
@Slf4j
public class ForkJoinTaskExample extends RecursiveTask<Integer> {
public static final int threshold = 2;
private int start;
private int end;
public ForkJoinTaskExample (int start, int end) {
this.start = start;
this.end = end;
}
@Override
protected Integer compute() {
int sum = 0;
//如果任务足够小就计算任务
boolean canCompute = (end - start) <= threshold;
if (canCompute) {
for (int i = start; i <= end; i++) {
sum += i;
}
} else {
//如果任务大于阈值,就分裂成两个子任务计算
int middle = (start + end) / 2;
ForkJoinTaskExample leftTask = new ForkJoinTaskExample(start, middle);
ForkJoinTaskExample rightTask = new ForkJoinTaskExample(middle + 1, end);
//执行任务
leftTask.fork();
rightTask.fork();
//任务结束后合并结果
int leftResult = leftTask.join();
int rightResult = rightTask.join();
//合并子任务
sum = leftResult + rightResult;
}
return sum;
}
public static void main(String[] args) {
ForkJoinPool forkJoinPool = new ForkJoinPool();
ForkJoinTaskExample task = new ForkJoinTaskExample(1, 100);
Future<Integer> result = forkJoinPool.submit(task);
try{
log.info("result:{}", result.get());
} catch (Exception e) {
log.error("exception", e);
}
}
}
复制代码
Overridden compute
method is to call itself recursively continue the great task split into small tasks, the final summary of the results of the final result.
BlockingQueue
BlockingQueue that is blocking queue.
Enqueue operation when the queue is full and blocking operations will be the team the thread into the blocked state when blocking queue is empty.
The main scenario for producers and consumers.
ArrayBlockingQueue
Fixed size, the internal array implementation is a need to specify initialization capacity can not be changed.
FIFO stored data, the latest data in the tail.
DelayQueue
Obstruction of internal elements. The JUC DelayQueue element must implement the interface in the Delay (Delay interface inherits the Comparable interface), generally to the priority element expiration time of order.
Internal implementation is a priority queue and lock.
LinkedBlockingQueue
The size of the configuration options, specify the size is bounded initialization, if not specified is borderless.
Internal implementation is the list, other features consistent with ArrayBlockingQueue.
PriorityBlockingQueue
No borders, there are collation allows you to insert null.
All PriorityBlockingQueue insert objects must implement the Comparable interface.
SynchronousQueue
Synchronization Queue
Internal allows only accommodate one element, it will be blocked after internal insert an element, unless this element is consumed by other threads.
Written by Autu
2019.7.21