Callable
(第三种线程实现方式)
Callable与Runnable的区别
Callable与Runnable的区别
实现方法名称不一样
有返回值
抛出了异常
class Thread1 implements Runnable{@Overridepublic void run() {
}
}
class Thread2 implements Callable<Integer>{//1.方法名称不一样 2.有返回值 3.抛出了异常@Overridepublic 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.抛出了异常@Overridepublic 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.抛出了异常@Overridepublic 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.抛出了异常@Overridepublic 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.抛出了异常@Overridepublic 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 thenit will be passed up the call stack */}}}