Java线程的创建,最基本的是用Thread,但是Java也提供了如下一些有用的方法,让线程的效率更高以及更好的控制。
关键类:Runnable、Callable、Executor、Future、FutureTask
在java5以后,一个可以调度执行的线程单元可以有三种方式定义:
Thread
Runnable
Callable
其中Runnable实现的是void run()方法,Callable实现的是 V call()方法,并且可以返回执行结果,其中Runnable可以提交给Thread来包装下,直接启动一个线程来执行,而Callable则一般都是提交给ExecuteService来执行。
简单来说,Executor就是Runnable和Callable的调度容器,Future就是对于具体的调度任务的执行结果进行查看,最为关键的是Future可以检查对应的任务是否已经完成,也可以阻塞在get方法上一直等待任务返回结果。Runnable和Callable的差别就是Runnable是没有结果可以返回的,就算是通过Future也看不到任务调度的结果的。
代码示例
package cn.myforever.test;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* 在Java5之后,任务分两类:一类是实现了Runnable接口的类,一类是实现了Callable接口的类。两者都可以被ExecutorService执行,但是Runnable任务没有返回值,而Callable任务有返回值。并且Callable的call()方法只能通过ExecutorService的(<T> task) 方法来执行,并且返回一个 <T><T>,是表示任务等待完成的 Future。
* @author forever
*
*/
public class SyncYBDO {
public static void main(String[] args) throws Throwable, ExecutionException {
ExecutorService executor1 = Executors.newFixedThreadPool(3);
// Future代表了线程执行完以后的结果,可以通过future获得执行的结果
// 但是jdk1.8之前的Future有点鸡肋,并不能实现真正的异步,需要阻塞的获取结果,或者不断的轮询
// 通常我们希望当线程执行完一些耗时的任务后,能够自动的通知我们结果,很遗憾这在原生jdk1.8之前
// 是不支持的,但是我们可以通过第三方的库实现真正的异步回调
Future<Boolean> f1 = executor1.submit(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
Thread.sleep(3000);
System.out.println("3秒任务执行结束");
return true;
}
});
Future<String> f2 = executor1.submit(new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(1000);
System.out.println("1秒任务执行结束");
return "success";
}
});
Future<String> f3 = executor1.submit(new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(2000);
System.out.println("2秒任务执行结束");
return "success";
}
});
//此处阻塞main线程 (也可以设置超时时间)
Boolean f1_result =f1.get();
String f2_result =f2.get();
}
}