一、实现Runnable接口
public classRunnableDemo implements Runnable {public voidrun() {try{
Thread.sleep(100);
}catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println("in runnable demo");
}
}
非阻塞调用
public static void main(String[] args) throwsException {
Thread runnableThread= new Thread(newRunnableDemo());runnableThread.start();
System.out.println("in main");
}
输出结果
in main
in runnable demo
可以看到线程的运行没有阻塞当前线程
阻塞调用
public static void main(String[] args) throwsException {
Thread runnableThread= new Thread(newRunnableDemo());
runnableThread.start();
runnableThread.join();
System.out.println("in main");
}
输出结果
in runnable demo
in main
Join会阻塞当前线程,一直等待自定义线程才返回。
二、实现Callable接口
在Runnable的例子中,Runnable接口有一个很大的缺陷就是run方法没有返回值定义,主线程无法获取到线程执行的结果。这个时候就需要Callable接口。
public class CallableDemo implements Callable{public CallableDtocall() throwsException {try{
Thread.sleep(100);
}catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println("in callable demo");return new CallableDto(1);
}
}classCallableDto {private intid;public CallableDto(intid) {this.id =id;
}public intgetId() {returnid;
}public void setId(intid) {this.id =id;
}
}
非阻塞调用
public static void main(String[] args) throwsException {
ThreadPoolExecutor executor= (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
Future future = executor.submit(newCallableDemo());
System.out.println("in main");
}
输出结果,如下所示,新启动的线程没有阻塞当前线程
in main
in callable demo
阻塞调用,且拿到结果
public static void main(String[] args) throwsException {
ThreadPoolExecutor executor= (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
Future future = executor.submit(newCallableDemo());
CallableDto callableDto=future.get();
System.out.println("in main");
System.out.println("id from callable is " +callableDto.getId());
}
get方法首先会阻塞主线程,等待当前线程执行结束才返回,且返回线程的执行结果。
三、CompletableFuture方式
CompletableFuture是jdk1.8引入的api,做了进一步的封装,用户线程无需实现Callable接口也能启动,且能够返回用户线程的执行结果
public static CompletableFuture supplyAsync(Supplier supplier, Executor executor)
一个没有实现Callable的普通方法
public classCompletableFutureDemo {publicCompletableFutureDemoDto action() {try{
Thread.sleep(100);
}catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println("in CompletableFutureDemo ");return new CompletableFutureDemoDto(1);
}
}classCompletableFutureDemoDto {private intid;public CompletableFutureDemoDto(intid) {this.id =id;
}public intgetId() {returnid;
}public void setId(intid) {this.id =id;
}
}
非阻塞调用
public static void main(String[] args) throwsException {
ThreadPoolExecutor executor= (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
CompletableFuture future = CompletableFuture.supplyAsync(() ->{return newCompletableFutureDemo().action();
}, executor);
System.out.println("in main");
}
执行结果,可以看到,主线程没有被阻塞
in main
in CompletableFutureDemo
阻塞调用且获取结果
public static void main(String[] args) throwsException {
ThreadPoolExecutor executor= (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
CompletableFuture future = CompletableFuture.supplyAsync(() ->{return newCompletableFutureDemo().action();
}, executor);
CompletableFutureDemoDto demoDto=future.join();
System.out.println("in main");
System.out.println("id from demoDto is " +demoDto.getId());
}
执行结果,主线程一直被阻塞,一直等到用户线程返回
in CompletableFutureDemo
in main
id from demoDto is1