中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

實現Java線程的方法有哪些

發布時間:2021-12-31 09:22:54 來源:億速云 閱讀:108 作者:iii 欄目:大數據

這篇文章主要介紹“實現Java線程的方法有哪些”,在日常操作中,相信很多人在實現Java線程的方法有哪些問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”實現Java線程的方法有哪些”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

搞懂兩件事: 為什么說本質上只有一種實現線程的方式? 實現 Runnable 接口究竟比繼承 Thread 類實現線程好在哪里?

一:常見的實現線程的方式

1:實現Runable接口

public class RunnableThread  implements Runnable{
    @Override
    public void run() {
        System.out.println("用實現Runnable接口實現線程");
    }
    public static void main(String[] args) {
        Thread thread=new Thread(new RunnableThread());
        thread.start();
    }
}

如代碼所示,首先通過 RunnableThread 類實現 Runnable 接口,然后重寫 run() 方法,之后只需要把這個實現了 run() 方法的實例傳到 Thread 類中就可以實現多線程。

2:繼承Thread類

public class ExtendsThread extends Thread{
    @Override
    public void run() {
        System.out.println("用繼承Thread類實現線程");
    }
}

與第 1 種方式不同的是它沒有實現接口,而是繼承 Thread 類,并重寫了其中的 run() 方法。

3:線程池創建線程

下面是線程池中的源碼,來看看線程池是怎么實現線程的:

    /**
     * The default thread factory
     */
    static class DefaultThreadFactory implements ThreadFactory {
        private static final AtomicInteger poolNumber = new AtomicInteger(1);
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        DefaultThreadFactory() {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() :
                                  Thread.currentThread().getThreadGroup();
            namePrefix = "pool-" +
                          poolNumber.getAndIncrement() +
                         "-thread-";
        }

        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r,
                                  namePrefix + threadNumber.getAndIncrement(),
                                  0);
            if (t.isDaemon())
                t.setDaemon(false);
            if (t.getPriority() != Thread.NORM_PRIORITY)
                t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }

對于線程池而言,本質上是通過線程工廠創建線程的,默認采用 DefaultThreadFactory ,它會給線程池創建的線程設置一些默認值,比如:線程的名字、是否是守護線程,以及線程的優先級等。但是最終都是通過new Thread()創建線程的,只是參數多了些而已

4:有返回值的 Callable 創建線程

public class CallableTask implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        return new Random().nextInt();
    }
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        Future<Integer> future = executorService.submit(new CallableTask());
        System.out.println(future.get());
        System.out.println(future.isDone());
        System.out.println(future.isCancelled());
    }
}

Runnable 創建線程是無返回值的,而 Callable 和與之相關的 Future、FutureTask,它們可以把線程執行的結果作為返回值返回,如代碼所示,實現了 Callable 接口,并且給它的泛型設置成 Integer,然后它會返回一個隨機數。

但是,無論是 Callable 還是 FutureTask,它們首先和 Runnable 一樣,都是一個任務,是需要被執行的,而不是說它們本身就是線程。它們可以放到線程池中執行,如代碼所示, submit() 方法把任務放到線程池中,并由線程池創建線程,不管用什么方法,最終都是靠線程來執行的,而子線程的創建方式仍脫離不了最開始講的兩種基本方式,也就是實現 Runnable 接口和繼承 Thread 類

5:匿名內部類、lambda表達式創建線程

    public static void innerClassThread(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("匿名內部類創建線程");
            }
        }).start();
    }

    public static void lambdaThread(){
       new Thread(()->{
           System.out.println("lambda表達式創建線程");
       }).start();
    }

實際上,匿名內部類或 lambda 表達式創建線程,它們僅僅是在語法層面上實現了線程,并不能把它歸結于實現多線程的方式,如匿名內部類實現線程的代碼所示,它僅僅是用一個匿名內部類把需要傳入的 Runnable 給實例出來。

二:為什么說本質上只有一種實現線程的方式?

了解了上面的幾種創建線程的方式后,我們發現所有其他創建線程的方式都僅僅是在 new Thread() 外做了一層封裝而已;不同點僅僅在于實現線程運行內容的不同。

  1. 實現線程執行的內容,通過實現 Runnable 接口的方式

啟動線程需要調用 start() 方法,而 start() 方法最終還會調用 run() 方法,Thread中的run()方法源碼如下:

    /* What will be run. */
    private Runnable target;
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
  • target其實就是一個Runnable,實際線程執行的內容就是實現了Runnable的接口中的run方法。

  1. 實現線程執行的內容,繼承 Thread 類重寫 run() 方法的方式

  • 啟動線程需要調用 start() 方法,而 start() 方法最終還會調用 run() 方法,但是此時的run()方法,因為繼承的原因,此時已被子類重寫了,所以此時線程執行的內容是子類的run方法

運行內容主要來自于兩個地方,要么來自于 target,要么來自于子類重寫的 run() 方法;因此可以這樣總結:本質上,實現線程只有一種方式new Thread(),而要想實現線程執行的內容,卻有兩種方式,要么通過實現 Runnable 接口的方式,要么繼承 Thread 類重寫 run() 方法的方式,把我們想要執行的代碼傳入,讓線程去執行

三:實現 Runnable 接口究竟比繼承 Thread 類實現線程好在哪里?

  1. Runnable 里只有一個 run() 方法,它定義了需要執行的內容,在這種情況下,實現了 Runnable 與 Thread 類的解耦,Thread 類負責線程啟動和屬性設置等內容,職責分明。

  2. java單繼承的原因,類一旦繼承了 Thread 類,那么它后續就沒有辦法再繼承其他的類,限制了代碼未來的可拓展性。

  3. 在某些情況下可以提高性能,如果使用繼承 Thread 類方式,每次執行一次任務,都需要新建一個獨立的線程;使用實現 Runnable 接口的方式,就可以把任務直接傳入線程池,使用一些固定的線程來完成任務,不需要每次新建銷毀線程,大大降低了性能開銷。

到此,關于“實現Java線程的方法有哪些”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

宁都县| 潜山县| 万州区| 尖扎县| 竹北市| 拉孜县| 龙江县| 永年县| 黑水县| 呼伦贝尔市| 娱乐| 封丘县| 镶黄旗| 祁东县| 涞水县| 尉氏县| 虎林市| 桓台县| 四川省| 孟连| 河间市| 绍兴县| 于都县| 蕉岭县| 简阳市| 丘北县| 金沙县| 盐亭县| 岑溪市| 凤台县| 阿城市| 承德县| 西宁市| 十堰市| 徐汇区| 桃园市| 临颍县| 河津市| 横峰县| 谢通门县| 上杭县|