Callable
(第三种线程实现方式)
Callable与Runnable的区别
Callable与Runnable的区别
实现方法名称不一样
有返回值
抛出了异常
class Thread1 implements Runnable{
@Override
public void run() {
}
}
class Thread2 implements Callable<Integer>{
//1.方法名称不一样 2.有返回值 3.抛出了异常
@Override
public Integer call() throws Exception {
return null;
}
}
Callable的使用
Callable线程类的运行,需要依靠FutureTask的封装,因为Thread类的构造方法只支持Runnable及其子类,于是就需要继承了Runnable的FutureTast来对Callable子类进行封装,下面是FurtureTast的继承关系源代码:
public class FutureTask<V> implements RunnableFuture<V> {public interface RunnableFuture<V> extends Runnable, Future<V> {
public class CallableDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<Integer> futureTask = new FutureTask<>(new Thread2());
new Thread(futureTask).start();
System.out.println(futureTask.get());
}
}
class Thread2 implements Callable<Integer>{
//1.方法名称不一样 2.有返回值 3.抛出了异常
@Override
public Integer call() throws Exception {
System.out.println("come in");
return 1024;
}
}
Callable的细节
使用callable就相当于另外开了一条线程运行,调用get方法就相当于要获取这条线程的运行结果。
如果在mian线程中调用了get方法,就会阻塞起来等待这个线程的运行结果。
于是就出现如下情况:
demo1
运行结果:
代码:
public class CallableDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<Integer> futureTask = new FutureTask<>(new Thread2());
new Thread(futureTask).start();
System.out.println("main");
System.out.println(futureTask.get()); //后调用get方法
}
}
class Thread2 implements Callable<Integer>{
//1.方法名称不一样 2.有返回值 3.抛出了异常
@Override
public Integer call() throws Exception {
Thread.sleep(2000);
System.out.println("come in");
return 1024;
}
}
demo2
运行结果:
代码:
public class CallableDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<Integer> futureTask = new FutureTask<>(new Thread2());
new Thread(futureTask).start();
System.out.println(futureTask.get()); //先调用get方法,会在这里等待线程返回结果
System.out.println("main");
}
}
class Thread2 implements Callable<Integer>{
//1.方法名称不一样 2.有返回值 3.抛出了异常
@Override
public Integer call() throws Exception {
Thread.sleep(2000);
System.out.println("come in");
return 1024;
}
}
Callable的细节2
callable多次运行,只会计算一次结果
运行结果:(可以看到 只执行了一次come in的输出,即call()这个方法的代码只运行了一次)
代码:
public class CallableDemo2 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<Integer> futureTask = new FutureTask<>(new Thread3());
Thread t1 = new Thread(futureTask); //第一次调用 这个 futruetask任务
t1.start();
Thread t2 = new Thread(futureTask); //第二次调用 这个 futruetask任务
t2.start();
System.out.println(futureTask.get());
System.out.println(futureTask.get());
System.out.println("main");
}
}
class Thread3 implements Callable<Integer>{
private static int num = 0;
//1.方法名称不一样 2.有返回值 3.抛出了异常
@Override
public Integer call() throws Exception {
System.out.println("come in");
return ++num;
}
}
原生Thread多次执行start会抛出IllegalThreadStateException非法的线程状态异常,Callable也是一样
Thread的start() 源码:
public synchronized void start() { /** * This method is not invoked for the main method thread or "system" * group threads created/set up by the VM. Any new functionality added * to this method in the future may have to also be added to the VM. * * A zero status value corresponds to state "NEW". */ if (threadStatus != 0) throw new IllegalThreadStateException(); //如果线程已经启动,则抛出异常 /* Notify the group that this thread is about to be started * so that it can be added to the group's list of threads * and the group's unstarted count can be decremented. */ group.add(this); boolean started = false; try { start0(); started = true; } finally { try { if (!started) { group.threadStartFailed(this); } } catch (Throwable ignore) { /* do nothing. If start0 threw a Throwable then it will be passed up the call stack */ } } }