Before JDK1.5 when we want to create a new thread, the most common way is to implements an interface called Runnable
.
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();
}
This interface has a run()
method with no return value.
Callable
Interface. This interface is added since JDK1.5.
It has a method called call()
with return generic type return value. And this method can throw Exception
.
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;
}
Example
The example below main
thread will sleep 6 seconds after submitting the task. When the main thread wakes up it will get the result from the created thread. That thread will return a random generate a double number.
package multithreading.createNewThread;
import java.util.concurrent.*;
public class CallableDemo {
public static void main(String[] args) {
TaskGetInteger taskGetInteger = new TaskGetInteger();
ExecutorService executorService = Executors.newFixedThreadPool(3);
try {
Future<Double> future = executorService.submit(new TaskGetInteger());
executorService.shutdown();
Thread.sleep(6000);
Double result = future.get();
System.out.println("result:" + result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
class TaskGetInteger implements Callable<Double> {
public Double call() throws Exception {
Thread.sleep(5000);
return Math.random();
}
}
Future Interface
Notice we use submit
method of ExecutorService
. This method will return a Future
object.
The Future
interface has several methods can help us
-
cancel the task
-
check the task is canceled or not
-
check if the task finishes running
-
get running result
-
get running result for the given time
public interface Future<V> {
/**
* Attempts to cancel execution of this task. This attempt will
* fail if the task has already completed, has already been cancelled,
* or could not be cancelled for some other reason. If successful,
* and this task has not started when {@code cancel} is called,
* this task should never run. If the task has already started,
* then the {@code mayInterruptIfRunning} parameter determines
* whether the thread executing this task should be interrupted in
* an attempt to stop the task.
*
* <p>After this method returns, subsequent calls to {@link #isDone} will
* always return {@code true}. Subsequent calls to {@link #isCancelled}
* will always return {@code true} if this method returned {@code true}.
*
* @param mayInterruptIfRunning {@code true} if the thread executing this
* task should be interrupted; otherwise, in-progress tasks are allowed
* to complete
* @return {@code false} if the task could not be cancelled,
* typically because it has already completed normally;
* {@code true} otherwise
*/
boolean cancel(boolean mayInterruptIfRunning);
/**
* Returns {@code true} if this task was cancelled before it completed
* normally.
*
* @return {@code true} if this task was cancelled before it completed
*/
boolean isCancelled();
/**
* Returns {@code true} if this task completed.
*
* Completion may be due to normal termination, an exception, or
* cancellation -- in all of these cases, this method will return
* {@code true}.
*
* @return {@code true} if this task completed
*/
boolean isDone();
/**
* Waits if necessary for the computation to complete, and then
* retrieves its result.
*
* @return the computed result
* @throws CancellationException if the computation was cancelled
* @throws ExecutionException if the computation threw an
* exception
* @throws InterruptedException if the current thread was interrupted
* while waiting
*/
V get() throws InterruptedException, ExecutionException;
/**
* Waits if necessary for at most the given time for the computation
* to complete, and then retrieves its result, if available.
*
* @param timeout the maximum time to wait
* @param unit the time unit of the timeout argument
* @return the computed result
* @throws CancellationException if the computation was canceled
* @throws ExecutionException if the computation threw an
* exception
* @throws InterruptedException if the current thread was interrupted
* while waiting
* @throws TimeoutException if the wait timed out
*/
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}