实现多线程的第三种方式Callable
- 实现线程的前两种方式
- Callable 与 Runnable
- Future
- FutureTask
- 示例
Java 实现多线程的二种方式:
方式一:继承Thread类
方式二:实现Runnable接口
示例代码如下:
// 方式一:继承Thread类
Thread thread01 = new Thread() {
@Override
public void run() {
System.out.println("线程二:hello");
}
};
thread01.start();
// 方式二:实现Runnable接口
Thread thread02 = new Thread(() -> System.out.println("线程三:hello"));
thread02.start();
这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果。
自从Java 1.5开始,就提供了Callable和Future,通过它们可以在任务执行完毕之后得到任务执行结果。
下面就来了解下Callable与Runnable
Callable 与 Runnable
Runnable接口,来自java.lang.Runnable,只声明了run()方法
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
由于run()方法返回值为void类型,所以在执行完任务之后无法返回任何结果。
Callable接口,来自java.util.concurrent.Callable<V>,也只声明了一个call()方法
@FunctionalInterface
public interface Callable<V> {
V call() throws Exception;
}
可以看到,这是一个泛型接口,call()函数返回的类型就是传递进来的V类型。
那么怎么使用Callable呢?一般情况下是配合ExecutorService来使用的
Future<T> submit(Callable<T> task);
接下来了解下Future
Future
Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果。
Future类位于java.util.concurrent包下,它是一个接口:
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;
}
也就是说Future提供了三种功能:
1)判断任务是否完成;
2)能够中断任务;
3)能够获取任务执行结果。
因为Future只是一个接口,所以是无法直接用来创建对象使用的,因此就有了下面的FutureTask。
FutureTask
![](https://img.haomeiwen.com/i1669182/34a533beb3da294d.png)
FutureTask类实现了RunnableFuture接口。
RunnableFuture继承了Runnable接口和Future接口,而FutureTask实现了RunnableFuture接口。所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。
FutureTask提供了2个构造器:
public FutureTask(Callable<V> callable) {}
public FutureTask(Runnable runnable, V result) {}
事实上,FutureTask是Future接口的一个唯一实现类。
示例:
了解了这些之后,下面是两个Callable的示例
示例一:Thread.start()启动线程
public static void main(String[] args) {
// 获取线程的返回值
AtomicInteger atomicInteger = new AtomicInteger(0);
FutureTask futureTask = new FutureTask(() -> {
atomicInteger.set(atomicInteger.get() + 1);
return atomicInteger.get();
});
Thread thread = new Thread(futureTask);
thread.start();
try {
System.out.println(
futureTask.get()
);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
示例二:通过ExecutorService执行线程
public static void main(String[] args) {
// 通过ExecutorService执行线程
AtomicInteger atomicInteger = new AtomicInteger();
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future submit = executorService.submit(() -> {
atomicInteger.set(atomicInteger.get() + 1);
return atomicInteger.get();
});
try {
System.out.println(
submit.get()
);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}