继承 Thread
new Thread(()->{
// do
},"A").start();
实现 Runable
new Thread(()->{
// do
},"A").start();
实现 Callable
class Job implements Runnable{
@Override
public void run() {
// do
}
}
与 Runable 的区别
实现 call() 而不是 run()
有返回值
会抛出异常
实现 线程池
public class CallableJob implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("=========");
return "used";
}
public static void main(String[] args) {
new Thread(new FutureTask<String>(new CallableJob())).start();
}
}
FutureTask 提供了 Callable 到 Runable 的适配(适配器模式)
通过此方式解决通过开启线程调用 Callable.call() 的目的
具体方式为:
实现了 Runable 接口,并且提供一个接受 Callable 的构造方法
//public interface RunnableFuture extends Runnable, Future
public class FutureTask<V> implements RunnableFuture<V> {
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW;
}
//FutureTask 中的 run()
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();// 在 run() 中调用 Callable 的 call()
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
} finally {
// ...
}
}
}
应用场景
相对于 Runable,Callable 提供一个返回值
并在结合 FutureTask 后,可以稍后获取到这个返回值
常用于分支-合并模式
即,在分步骤业务中,另开线程处理复杂或耗时的环节,并最终汇总结果
public class CallableJob implements Callable<Integer> {
@Override
public Integer call() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 100 * 1000;
}
public static Integer smallJob(Integer... eles){
return Arrays.stream(eles).mapToInt(Integer::intValue).sum();
}
public static void main(String[] args) {
FutureTask<Integer> bigJob = new FutureTask<Integer>(new CallableJob());
try {
new Thread(bigJob).start();
int result = smallJob(1,2,3,4,5);
result += bigJob.get();
System.out.println(result);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
注意
TimeoutExceptionwhile (!bigJob.isDone()){
System.out.println("working");
TimeUnit.MILLISECONDS.sleep(500);
}
result += bigJob.get();