Future Start
学习 Future
之前先简单的学习一下 Callable
和 Runnable
Callable 和 Runnable
Java
多线程实现方式主要有四种:
- 继承
Thread
类 - 实现
Runnable
接口 - 实现
Callable
接口通过FutureTask
包装器来创建Thread
线程、 - 使用
ExecutorService、Callable、Future
实现有返回结果的多线程。
Runnable
代码
package java.lang;
@FunctionalInterface
public interface Runnable {
void run();
}
- 由于
run()
方法返回值为void
类型,所以在执行完任务之后无法返回任何结果。 - 使用示例1
public class MyTask implements Runnable{
CountDownLatch latch;
public MyTask(CountDownLatch latch){
this.latch = latch;
}
public MyTask(){
this.latch = null;
}
@Override
public void run(){
try{
System.out.println("Starting my task");
Thread.sleep(1000);
System.out.println("Done my task");
} catch (InterruptedException e){
System.out.println(e.fillInStackTrace());
} finally {
if(this.latch != null){
latch.countDown();
}
}
}
}
@Test
public void testRunnable()throws InterruptedException{
Thread thread = new Thread(new MyTask());
thread.start();
thread.join();
}
- 使用示例2
public void testRunnable1()throws InterruptedException{
ExecutorService service = Executors.newFixedThreadPool(1);
service.execute(new MyTask());
service.shutdown();
/**主线程等待子线程执行结束再结束**/
try {
service.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
System.out.println(e.fillInStackTrace());
}
}
/**使用CountDownLatch使主进程等待子进程**/
@Test
public void testRunnable2()throws InterruptedException{
CountDownLatch latch = new CountDownLatch(1);
ExecutorService service = Executors.newFixedThreadPool(1);
service.execute(new MyTask(latch));
try {
System.out.println("Waiting one sub thread ...");
latch.await();
System.out.println("Sub thread all donne");
System.out.println("Continuing main thread");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Callable
接口定义
@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;
}
- 这是一个泛型接口,
call()
函数返回的类型就是传递进来的V
类型。 Callable
一般与FutureTask
配合使用,FutureTask
使用参照下面的内容- 示例1
public class MyCallable implements Callable<String>{
private String context;
public MyCallable(String context){
this.context = context;
}
@Override
public String call(){
try{
Thread.sleep(1000);
return this.context + " append something";
} catch (InterruptedException e){
e.printStackTrace();
}
return this.context;
}
}
@Test
public void testCallable()throws ExecutionException,InterruptedException{
Callable<String> mCallable = new MyCallable("Wether is good.");
FutureTask<String> task = new FutureTask<>(mCallable);
Thread thread = new Thread(task);
thread.start();
//调用get方法阻塞主线程
String result = task.get();
System.out.println(result);
}
- 示例2 使用线程池
@Test
public void testCallable2()throws ExecutionException,InterruptedException{
ExecutorService service = Executors.newFixedThreadPool(1);
Callable<String> mCallable = new MyCallable("Wether is good.");
FutureTask<String> task = new FutureTask<>(mCallable);
service.execute(task);
//调用get方法阻塞主线程
String result = task.get();
System.out.println(result);
}
- 示例3 使用线程池
@Test
public void testCallable3()throws ExecutionException,InterruptedException{
ExecutorService service = Executors.newFixedThreadPool(1);
Callable<String> mCallable = new MyCallable("Wether is good.");
Future<String> future = service.submit(mCallable);
//调用get方法阻塞主线程
String result = future.get();
System.out.println(result);
}
FutureTask
代码
public interface RunnableFuture<V> extends Runnable, Future<V> {
/**
* Sets this Future to the result of its computation
* unless it has been cancelled.
*/
void run();
}
public class FutureTask<V> implements RunnableFuture<V> {
...
}
- 可以看出
RunnableFuture
继承了Runnable
接口和Future
接口,而FutureTask
实现了RunnableFuture
接口。 - 可见
FutureTask
是Runnable
和Future
接口的实现 - 所以它既可以作为
Runnable
被线程执行,又可以作为Future
得到Callable
的返回值。
Future
如上面的介绍,Future
的两种典型用法,这两种用法的主要不同点就是线程池使用 execute、submit
执行的区别。但是 Future
有个明显的缺点,get
方法会阻塞当前线程,也就下面的两种用法只能串行执行。这和我们预想的不太一样,这也是下面要学习的 CompletableFuture
所要解决的问题。
@Test
public void testFuture()throws ExecutionException,InterruptedException{
//用法一
ExecutorService service = Executors.newFixedThreadPool(2);
Callable<String> mCallable = new MyCallable("Wether is good.");
FutureTask<String> task = new FutureTask<>(mCallable);
service.execute(task);
//调用get方法阻塞主线程
String result = task.get();
System.out.println(result);
//用法二
Callable<String> mCallable1 = new MyCallable("Wether is good.");
Future<String> future1 = service.submit(mCallable);
//调用get方法阻塞主线程
String result1 = future1.get();
System.out.println(result1);
}
本文由 zealzhangz 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为:
2019/02/14 20:35