1. 程式人生 > >多線程編程之Runnable與Callable區別

多線程編程之Runnable與Callable區別

cond 的區別 stat result tel 基本上 ace 哈哈 separate

Runnable
@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object‘s
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

Callable

@FunctionalInterface
public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

相同點:
1.都是接口,都能夠實現多線程編程,都需要Thread.start()來啟動線程。

不同點:
1.Callable接口支持返回執行結果,此時需要調用FutureTask.get()方法實現,此方法會阻塞主線程直到獲取‘將來’結果;當不調用此方法時,主線程不會阻塞!

Callable使用

/**
 * CallableImpl 簡要描述
 * <p> TODO:描述該類職責 </p>
 *
 * @author ckmike
 * @version 1.0
 * @date 18-12-6 下午8:53
 * @copyright ckmike
 **/
public class CallableImpl implements Callable<String> {

    private String accept;

    public CallableImpl(String accept) {
        this.accept = accept;
    }

    @Override
    public String call() throws Exception {
        // 休眠
        TimeUnit.SECONDS.sleep(3);
        return this.accept;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Callable<String> callable = new CallableImpl("my callable test!");
        FutureTask<String> task = new FutureTask<>(callable);
        long beginTime = System.currentTimeMillis();
        // 創建線程
        new Thread(task).start();
        // 調用get()阻塞主線程,反之,線程不會阻塞
        String result = task.get();
        long endTime = System.currentTimeMillis();
        System.out.println("hello : " + result);
        System.out.println("cast : " + (endTime - beginTime) / 1000 + " second!");
    }
}

Runnable使用

/**
 * RunnableImpl 簡要描述
 * <p> TODO:描述該類職責 </p>
 *
 * @author ckmike
 * @version 1.0
 * @date 18-12-6 下午9:03
 * @copyright ckmike
 **/
public class RunnableImpl implements Runnable {

    public RunnableImpl(String accept) {
        this.accept = accept;
    }

    private String accept;

    @Override
    public void run() {
        // 線程阻塞 1 秒,此時有異常產生,只能在方法內部消化,無法上拋
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 最終處理結果無法返回
        System.out.println("hello : " + this.accept);
    }

    public static void main(String[] args) {
        Runnable runnable = new RunnableImpl("my runable test!");
        long beginTime = System.currentTimeMillis();
        new Thread(runnable).start();
        long endTime = System.currentTimeMillis();
        System.out.println("cast : " + (endTime - beginTime) / 1000 + " second!");
    }
}

寫這篇文章的原因是:面試時問道Runnable與Callable的區別,平時也就用Runnable比較多,基本上沒有用過Callable,所以就掛了,哈哈哈,也總結給有需要的朋友。有知道Callable接口的使用場景嗎?有的話可以留意分享給我嗎?謝謝了!

多線程編程之Runnable與Callable區別