Java 线程 : Runnable与Callable区别

mac2024-04-04  55

参考:

Java Runnable与Callable区别

Callable 与 Runnable 对比:

相同:都是可被其它线程执行的任务。

不同:

①Callable规定的方法是call(),而Runnable规定的方法是run().

②Callable的任务执行后可返回值,而Runnable的任务是不能返回值的

③call()方法可抛出异常,而run()方法是不能抛出异常的。

④运行Callable任务可拿到一个Future对象,Future表示异步计算的结果。通过Future对象可了解任务执行情况,可取消任务的执行。

public interface Callable<V> { V call() throws Exception; } public interface Runnable { void run(); } 相同点

都是接口

都可以编写多线程程序

都采用Thread.start()启动线程

不同点

Runnable没有返回值;Callable可以返回执行结果,是个泛型,和Future、FutureTask配合可以用来获取异步执行的结果

Callable接口的call()方法允许抛出异常;Runnable的run()方法异常只能在内部消化,不能往上继续抛

注:Callalbe接口支持返回执行结果,需要调用FutureTask.get()得到,此方法会阻塞主进程的继续往下执行,如果不调用不会阻塞。

示例一:

import java.util.Random; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class CallableAndFuture { public static void main(String[] args) { Callable<Integer> callable = new Callable<Integer>() { @Override public Integer call() throws Exception { Thread.sleep(6000); return new Random().nextInt(); } }; FutureTask<Integer> future = new FutureTask<>(callable); new Thread(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 | ExecutionException e) { e.printStackTrace(); } } } //----hello begin---- //false //148033037 //true //----hello end----

示例二:

import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class CallableThreadTest implements Callable<Integer> { public static void main(String[] args) throws ExecutionException, InterruptedException { CallableThreadTest ctt = new CallableThreadTest(); FutureTask<Integer> futureTask = new FutureTask<>(ctt); new Thread(futureTask, "有返回值的线程").start(); System.out.println("子线程的返回值" + futureTask.get()); } @Override public Integer call() { int i; for (i = 0; i < 10; i += 2) { System.out.println(Thread.currentThread().getName() + " " + i); } return i; } } //有返回值的线程 0 //有返回值的线程 2 //有返回值的线程 4 //有返回值的线程 6 //有返回值的线程 8 //子线程的返回值10

示例三:

多线程返回执行结果是很有用的一个特性, 因为多线程相比单线程更难、更复杂的一个重要原因就是因为多线程充满着未知性,

某条线程是否执行了?某条线程执行了多久?某条线程执行的时候我们期望的数据是否已经赋值完毕?

无法得知,我们能做的只是等待这条多线程的任务执行完毕而已。 而Callable+Future/FutureTask却可以获取多线程运行的结果, 可以在等待时间太长没获取到需要的数据的情况下取消该线程的任务,真的是非常有用。

import java.util.Random; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class CallableAndFuture2 { public static void main(String[] args) { Callable<Integer> callable = new Callable<Integer>() { @Override public Integer call() throws Exception { Thread.sleep(6000); return new Random().nextInt(); } }; FutureTask<Integer> futureTask = new FutureTask<>(callable); new Thread(futureTask).start(); try { Thread.sleep(1000); System.out.println("----hello begin----"); System.out.println(futureTask.isDone()); futureTask.cancel(false); //取消 if (!futureTask.isCancelled()) { System.out.println(futureTask.get()); System.out.println(futureTask.isDone()); System.out.println("----hello end----"); } else { System.out.println("______cancel_____"); } } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } } } //----hello begin---- //false //______cancel_____
最新回复(0)