区别1: 两者最大的区别,实现Callable接口的任务线程能返回执行结果,而实现Runnable接口的任务线程不能返回执行结果
注意点:Callable接口支持返回执行结果,此时需要调用FutureTask.get()方法实现,此方法会阻塞线程直到获取“将来”的结果,当不调用此方法时,主线程不会阻塞
区别2:Callable接口实现类中run()方法允许将异常向上抛出,也可以直接在内部处理(try...catch); 而Runnable接口实现类中run()方法的异常必须在内部处理掉,不能向上抛出
Demo1: Callable接口测试
package com.cc.io.currentthread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class CallableTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Callable<String> callable = new CallableImpl(" my callable test");
FutureTask<String> task = new FutureTask<>(callable);
Long beginTime = System.currentTimeMillis();
new Thread(task).start();
String result = task.get();
Long endTime = System.currentTimeMillis();
System.out.println("hello," + result);
System.out.println("cast:" + (endTime-beginTime)/1000);
}
}
class CallableImpl implements Callable<String> {
private String str;
public CallableImpl(String str) {
this.str = str;
}
@Override
public String call() throws Exception {
Thread.sleep(1000);
return this.str + " append some chars and return it";
}
}
Demo2: Runnable接口测试
package com.cc.io.currentthread;
public class RunnableTest {
public static void main(String[] args) {
Runnable runnable = new RunnableImpl("my runnable test");
Long beginTime = System.currentTimeMillis();
new Thread(runnable).start();
Long endTime = System.currentTimeMillis();
System.out.println("cast:" + (endTime-beginTime)/1000);
}
}
class RunnableImpl implements Runnable {
private String str;
public RunnableImpl(String str) {
this.str = str;
}
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("hello:" + this.str);
}
}