java面試常問的Runnable和Callable的區別
Runnable
Runnable接口非常簡單,就定義瞭一個方法run(), 實現Runnable接口的run方法就可以實現多線程
// 函數式接口 @FunctionalInterface public interface Runnable { public abstract void run(); }
Callable
可能很多人都知道要想在多線程中獲取異步返回值結果一般是用Callable和FutureTask接口來實現,但可能很多人都不知道其實Callable是依賴於Runnable的run方法進行執行任務的,然後在通過FutureTask來收集返回值結果,下面咱們就自己模擬寫一份FutureTask代碼來看看是怎麼實現的吧。
/** * @author yinfeng * @description 自己實現futureTask,基於park/unpark進行線程通訊 * @since 2022/1/9 21:32 */ public class MyFutureTask<T> implements Runnable { Callable<T> callable; /** * callable執行結果 */ T result; /** * task執行狀態 */ String state = "new"; /** * 存儲正在等待的消費者 */ LinkedBlockingQueue<Thread> waiters = new LinkedBlockingQueue<>(); public MyFutureTask(Callable<T> callable) { this.callable = callable; } @Override public void run() { try { result = callable.call(); } catch (Exception e) { e.printStackTrace(); } finally { state = "end"; } // 任務執行完成後通過unpark通知消費者 System.out.println(Thread.currentThread().getName() + " 生產者執行結束,通知消費者"); while (true) { Thread waiter = waiters.poll(); if (waiter == null) { break; } LockSupport.unpark(waiter); } } /** * park / unpark */ public T get() throws Exception { Thread mainThread = Thread.currentThread(); // 塞入等待的集合中 waiters.add(mainThread); // 判斷狀態 System.out.println(Thread.currentThread().getName() + " 消費者進入等待"); while (!"end".equals(state)) { // 阻塞等待任務執行完成後通知 LockSupport.park(mainThread); } return result; } }
我們寫個demo測試一下
/** * @author yinfeng * @description * @since 2022/1/9 21:32 */ public class FutureTaskTest { public static void main(String[] args) throws Exception { final MyFutureTask<String> futureTask = new MyFutureTask<>(() -> { Thread.sleep(5000); return "任務完成888"; }); new Thread(futureTask).start(); final String result = futureTask.get(); System.out.println("結果:"+result); // 控制臺打印如下: // main 消費者進入等待 // Thread-0 生產者執行結束,通知消費者 // 結果:任務完成888 } }
可以看到我們的demo也是正常運行的,所以很關鍵的一點還是Callable是依賴於Runnable的run方法進行執行任務的
到此這篇關於java面試常問的Runnable和Callable的區別的文章就介紹到這瞭,更多相關java Runnable和Callable區別內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Java使用Runnable和Callable實現多線程的區別詳解
- Java線程的三種創建方式
- Java創建線程及配合使用Lambda方式
- java ThreadPoolExecutor線程池拒絕策略避坑
- Java多線程 Callable、Future 和FutureTask