接口定义
#Callable接口
public interface Callable{
V call()throwsException;
}
#Runnable接口
public interfaceRunnable {public abstract voidrun();
}
相同点
都是接口
都可以编写多线程程序
都采用Thread.start()启动线程
不同点
Runnable没有返回值;Callable可以返回执行结果,是个泛型,和Future、FutureTask配合可以用来获取异步执行的结果
Callable接口的call()方法允许抛出异常;Runnable的run()方法异常只能在内部消化,不能往上继续抛
注:Callalble接口支持返回执行结果,需要调用FutureTask.get()得到,此方法会阻塞主进程的继续往下执行,如果不调用不会阻塞。
示例
#Callable-1
importjava.util.Random;importjava.util.concurrent.Callable;importjava.util.concurrent.ExecutionException;importjava.util.concurrent.FutureTask;public classCallableAndFuture {public static voidmain(String[] args) {
Callable callable = new Callable() {
@Overridepublic Integer call() throwsException {
Thread.sleep(6000);return newRandom().nextInt();
}
};
FutureTask future = new FutureTask<>(callable);newThread(future).start();try{
Thread.sleep(1000);
System.out.println("hello begin");
System.out.println(future.isDone());
System.out.println(future.get());
System.out.println(future.isDone());
System.out.println("hello end");
}catch(InterruptedException e) {
e.printStackTrace();
}catch(ExecutionException e) {
e.printStackTrace();
}
}
}
结果
hello beginfalse
1664014921
truehello end
#Callable-2
importjava.util.concurrent.Callable;importjava.util.concurrent.ExecutionException;importjava.util.concurrent.FutureTask;public class CallableThreadTest implements Callable{public static void main(String[] args) throwsExecutionException, InterruptedException {
CallableThreadTest ctt= newCallableThreadTest();
FutureTask ft = new FutureTask<>(ctt);new Thread(ft, "有返回值的线程").start();
System.out.println("子线程的返回值" +ft.get());
}
@OverridepublicInteger call() {inti;for (i = 0; i < 10; i += 2) {
System.out.println(Thread.currentThread().getName()+ " " +i);
}returni;
}
}
结果
有返回值的线程 0有返回值的线程2有返回值的线程4有返回值的线程6有返回值的线程8子线程的返回值10
优势
多线程返回执行结果是很有用的一个特性,因为多线程相比单线程更难、更复杂的一个重要原因就是因为多线程充满着未知性,某条线程是否执行了?某条线程执行了多久?某条线程执行的时候我们期望的数据是否已经赋值完毕?无法得知,我们能做的只是等待这条多线程的任务执行完毕而已。而Callable+Future/FutureTask却可以获取多线程运行的结果,可以在等待时间太长没获取到需要的数据的情况下取消该线程的任务,真的是非常有用。
public classCallableAndFuture {public static voidmain(String[] args) {
Callable callable = new Callable() {
@Overridepublic Integer call() throwsException {
Thread.sleep(6000);return newRandom().nextInt();
}
};
FutureTask future = new FutureTask<>(callable);newThread(future).start();try{
Thread.sleep(1000);
System.out.println("hello begin");
System.out.println(future.isDone());//future.cancel(false);
if (!future.isCancelled()) {
System.out.println(future.get());
System.out.println(future.isDone());
System.out.println("hello end");
}else{
System.out.println("cancel~");
}
}catch(InterruptedException e) {
e.printStackTrace();
}catch(ExecutionException e) {
e.printStackTrace();
}
}
}