1. 程式人生 > 其它 >Java JUC併發之Callable介面

Java JUC併發之Callable介面

七、 Callable

相較於Runnable來說,Callable => :

  • 可以有返回值
  • 可以丟擲異常
  • 方法不同, run() => Runnable、 call() => Callable

程式碼測試

package com.liu.callable;

import java.util.concurrent.*;

public class CallableTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        // new Thread( new Runnable() ).start();
        // new Thread( new FutureTask<V>() ).start();
        // new Thread( new FutureTask<V>( Callable) ).start();
        // new Thread().start() 怎麼啟動Callable 使用適配類 FutureTask


        MyThread thread = new MyThread();
        FutureTask futureTask = new FutureTask(thread); // FutureTask => 適配類
        new Thread(futureTask,"A").start();
        new Thread(futureTask,"B").start(); // 結果會被快取,可以提高效率


        String r = (String) futureTask.get(); // 獲取返回結果 get()可能會產生阻塞 將它放到最後 或者 使用非同步通訊

        System.out.println(r);

       /* // 建立執行服務
        ExecutorService service = Executors.newFixedThreadPool(1);

        // 提交執行
        Future<String> res = service.submit(thread);

        // 獲得執行結果
        try {
            String r = res.get();
            System.out.println(r);

        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        // 關閉服務
        service.shutdown();*/

    }
}

class MyThread implements Callable<String> {

    @Override
    public String call() throws Exception {
        System.out.println("call()");
        return "ybb";
    }
}

FutureTask原始碼中的run() :

    private volatile int state;
    private static final int NEW          = 0;
    private static final int COMPLETING   = 1;
    private static final int NORMAL       = 2;
    private static final int EXCEPTIONAL  = 3;
    private static final int CANCELLED    = 4;
    private static final int INTERRUPTING = 5;
    private static final int INTERRUPTED  = 6;

public void run() {
       // 如果執行緒已經被執行過一次(不處於新生狀態),則直接返回 
       // 對 FutureTask中 的 volatile 型別的變數 state(當前執行緒的狀態) 進行判斷  
        if (state != NEW ||
            !RUNNER.compareAndSet(this, null, Thread.currentThread()))
            return;
        try {
            Callable<V> c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call();
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
                if (ran)
                    set(result);
            }
        } finally {
            // runner must be non-null until state is settled to
            // prevent concurrent calls to run()
            runner = null;
            // state must be re-read after nulling runner to prevent
            // leaked interrupts
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }

總結:

  1. Callable可以有返回值,也可以丟擲異常;
  2. Callable需要使用適配類FutureTask來啟動;
  3. Callable實現的多執行緒有快取,結果可能需要等待,會阻塞!

本文來自部落格園,作者:{夕立君},轉載請註明原文連結:https://www.cnblogs.com/liuzhhhao/p/15016377.html