6、Callable接口的使用(簡單)


引用學習(狂神說)

使用解析

1、首先查看官方文檔和源碼是如何講解的

 

可以知道以下幾點:

1、Callable接口類似於Runnable接口

2、Callable有返回值

3、Callable可以拋出異常

4、調用call()方法

5、Callable支持泛型

2、既然和Runnable接口類似,就直接創建一下

class MyThread implements Callable<String>{

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

}

3、重點:如何啟動呢?

要知道線程的啟動只能通過 new Thread().start()

  • Thread的構造方法中,只能丟入Runnable接口

那該怎么辦?

現在知道的是Thread類,和Runnable接口有關系,我們是否可以通過Runnable接口和Thread類掛上關系呢?

通過圖解拆分關系

  • 現在你是Callable接口,Runnable接口是的女朋友,Thread類是你女朋友的閨蜜

  • 而現在你想認識你女朋友的閨蜜,怎么辦呢?

  • 如果你直接去找你女朋友的閨蜜,肯定會有些突兀或者造成誤會!

  • 肯定需要通過你女朋友的介紹,對吧!

  • 那么你的女朋友要如何介紹呢?這是一個問題!

4、查看Runnable接口在文檔中的說明

Runnable接口本身沒有說明好看的,只是一個函數式接口,里面有個run()方法,僅此而已!

但是它有兩個重要的實現類,圖中已經標出:

點開實現類FutureTask

往下翻,在構造器中你會發現可以丟入一個Callable接口

 那么現在就可以通過FutureTask實現類和Thread類掛上關系了!

具體使用

有兩個坑,需要注意返回參數和緩存

創建Callable線程並啟動

package com.zxh.callable;

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

public class CallableTest {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        FutureTask futureTask = new FutureTask(myThread);   // 適配器類

        new Thread(futureTask).start();
    }
}
class MyThread implements Callable<String>{

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

}

Callable返回的參數和注意點

獲取返回的參數

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class CallableTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        MyThread myThread = new MyThread();
        FutureTask futureTask = new FutureTask(myThread);   // 適配器類

        new Thread(futureTask).start();

        Object o = futureTask.get();
        System.out.println(o);
    }
}
class MyThread implements Callable<String>{

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

}

注意點

futureTask.get()方法可能會阻塞

因為call()中可能會存在耗時的任務,所以在獲取返回值的時候,就會等待(阻塞)。

一般將get()方法放在最后一行,並用通過異步操作調用。

緩存

  • 當你使用兩個線程調用的時候,會發現輸出只有1次。

  • 因為結果被緩存,提高了效率

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class CallableTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        MyThread myThread = new MyThread();
        FutureTask futureTask = new FutureTask(myThread);   // 適配器類

        new Thread(futureTask, "A").start();
        new Thread(futureTask, "B").start();    //結果會被緩存

        Object o = futureTask.get();    // 會阻塞,一般通過異步操作
        System.out.println(o);
    }
}
class MyThread implements Callable<String>{

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

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM