#Callable接口java
public interface Callable<V> { V call() throws Exception; }
#Runnable接口多線程
public interface Runnable { public abstract void run(); }
都是接口dom
均可以編寫多線程程序異步
都採用Thread.start()啓動線程ide
Runnable沒有返回值;Callable能夠返回執行結果,是個泛型,和Future、FutureTask配合能夠用來獲取異步執行的結果spa
Callable接口的call()方法容許拋出異常;Runnable的run()方法異常只能在內部消化,不能往上繼續拋線程
注:Callalbe接口支持返回執行結果,須要調用FutureTask.get()獲得,此方法會阻塞主進程的繼續往下執行,若是不調用不會阻塞。code
#Callable-1blog
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 e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }
結果接口
hello begin false 1664014921 true hello end
#Callable-2
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> ft = new FutureTask<>(ctt); new Thread(ft, "有返回值的線程").start(); System.out.println("子線程的返回值" + ft.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卻能夠獲取多線程運行的結果,能夠在等待時間太長沒獲取到須要的數據的狀況下取消該線程的任務,真的是很是有用。
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()); // future.cancel(false); if (!future.isCancelled()) { System.out.println(future.get()); System.out.println(future.isDone()); System.out.println("hello end"); } else { System.out.println("cancel~"); } } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }