最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java 多線程之兩步掌握

 更新時間:2021年10月08日 10:12:40   作者:愛敲代碼的小高  
Java 多線程編程 Java給多線程編程提供了內(nèi)置的支持。一條線程指的是進程中一個單一順序的控制流,一個進程中可以并發(fā)多個線程,每條線程并行執(zhí)行不同的任務(wù)

導(dǎo)論:初識多線程

首先,我們來討論討論什么叫做多線程。舉個簡單的例子,比如說造房子這個任務(wù)。如果只有一個人的話,他既要搬磚還得拎砂漿、攪拌水泥之類的(其他工種這里就不一一闡述了),哪怕這個工人技術(shù)再熟練,精力再旺盛,他同時也只能干一個工種。那么問題來了,該如何提升效率呢?很簡單,我們可以請多個工人同時來干活,可以同時干多種也可以干同種活兒,這樣效率就高得多。盡管他們各自可干著不同的活兒,但本質(zhì)都是為了造房子這個任務(wù),這就叫做多進程,即將一個大任務(wù)拆分成不同的小任務(wù),分配不同的人來執(zhí)行,當(dāng)包工頭也就是處理器下達命令時,他們按照指令來工作。

每個工種的話,比如攪拌水泥的大工優(yōu)惠叫來幾個小工,都是來干攪拌水泥這個活兒,所以這里叫做多線程。

那么,怎么區(qū)分多進程和多線程呢?這里簡單概括:

進程是系統(tǒng)分配資源的最小單位,線程是系統(tǒng)調(diào)度的最小單位。一個進程內(nèi)的線程之間是可以共享資源的。 每個進程至少有一個線程存在,即主線程。

一:動手來創(chuàng)建多線程

1.1 創(chuàng)建一個主線程

請看代碼:

public class ThreadDemo1 {
    static class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println("hello world, 我是一個線程");
            while (true) {
 
            }
        }
    }
 
    public static void main(String[] args) {
        // 創(chuàng)建線程需要使用 Thread 類, 來創(chuàng)建一個 Thread 的實例.
        // 另一方面還需要給這個線程指定, 要執(zhí)行哪些指令/代碼.
        // 指定指令的方式有很多種方式, 此處先用一種簡單的, 直接繼承 Thread 類,
        // 重寫 Thread 類中的 run 方法.
 
        // [注意!] 當(dāng) Thread 對象被創(chuàng)建出來的時候, 內(nèi)核中并沒有隨之產(chǎn)生一個線程(PCB).
        Thread t = new MyThread();
        // 執(zhí)行這個 start 方法, 才是真的創(chuàng)建出了一個線程.
        // 此時內(nèi)核中才隨之出現(xiàn)了一個 PCB, 這個 PCB 就會對應(yīng)讓 CPU 來執(zhí)行該線程的代碼. (上面的 run 方法中的邏輯)
        t.start();
 
        while (true) {
            // 這里啥都不干
        }
    }
}

接下里,我們可以通過jdk里面的一個jconsole來查看,我的文件路徑是C:\Program Files\Java\jdk1.8.0_192\bin,大家可以對照自己安裝的jdk文件位置來尋找。運行程序,打開jconsole可以看下

這里這個主線程就是我們創(chuàng)建的線程,線程創(chuàng)建成功。

1.2 多線程搶占式執(zhí)行

創(chuàng)建兩個線程,輸出線程運行前后時間,多次運行發(fā)現(xiàn)運行時間不一,這里就體現(xiàn)了現(xiàn)成的搶占式執(zhí)行方法,看代碼:

public class ThreadDemo2 {
    private static long count = 100_0000_0000L;
 
    public static void main(String[] args) {
        // serial();
        concurrency();
    }
 
    private static void serial() {
        long beg = System.currentTimeMillis();
 
        int a = 0;
        for (long i = 0; i < count; i++) {
            a++;
        }
        int b = 0;
        for (long i = 0; i < count; i++) {
            b++;
        }
 
        long end = System.currentTimeMillis();
        System.out.println("time: " + (end - beg) + " ms");
    }
 
    private static void concurrency() {
        long beg = System.currentTimeMillis();
 
        Thread t1 = new Thread() {
            @Override
            public void run() {
                int a = 0;
                for (long i = 0; i < count; i++) {
                    a++;
                }
            }
        };
 
        Thread t2 = new Thread() {
            @Override
            public void run() {
                int b = 0;
                for (long i = 0; i < count; i++) {
                    b++;
                }
            }
        };
        t1.start();
        t2.start();
 
        try {
            // 線程等待. 讓主線程等待 t1 和 t2 執(zhí)行結(jié)束, 然后再繼續(xù)往下執(zhí)行.
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
 
        // t1 t2 和 main 線程之間都是并發(fā)執(zhí)行的.
        // 調(diào)用了 t1.start 和 t2.start 之后, 兩個新線程正在緊鑼密鼓的進行計算過程中,
        // 此時主線程仍然會繼續(xù)執(zhí)行, 下面的 end 就隨之被計算了.
        // 正確的做法應(yīng)該是要保證 t1 和 t2 都計算完畢, 再來計算這個 end 的時間戳.
        long end = System.currentTimeMillis();
        System.out.println("time: " + (end - beg) + " ms");
    }
}

多次運行,會有以下結(jié)果:

可以發(fā)現(xiàn)線程是搶占式執(zhí)行。

我們用join關(guān)鍵字,可以規(guī)定線程運行先后順序,比如這里規(guī)定t1運行完后t2再運行,代碼如下:

public class ThreadDemo2 {
    private static long count = 100_0000_0000L;
 
    public static void main(String[] args) {
         serial();
        //concurrency();
    }
 
    private static void serial() {
        long beg = System.currentTimeMillis();
 
        int a = 0;
        for (long i = 0; i < count; i++) {
            a++;
        }
        int b = 0;
        for (long i = 0; i < count; i++) {
            b++;
        }
 
        long end = System.currentTimeMillis();
        System.out.println("time: " + (end - beg) + " ms");
    }
 
    private static void concurrency() {
        long beg = System.currentTimeMillis();
 
        Thread t1 = new Thread() {
            @Override
            public void run() {
                int a = 0;
                for (long i = 0; i < count; i++) {
                    a++;
                }
            }
        };
 
        Thread t2 = new Thread() {
            @Override
            public void run() {
                int b = 0;
                for (long i = 0; i < count; i++) {
                    b++;
                }
            }
        };
        t1.start();
        t2.start();
 
        try {
            // 線程等待. 讓主線程等待 t1 和 t2 執(zhí)行結(jié)束, 然后再繼續(xù)往下執(zhí)行.
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
 
        // t1 t2 和 main 線程之間都是并發(fā)執(zhí)行的.
        // 調(diào)用了 t1.start 和 t2.start 之后, 兩個新線程正在緊鑼密鼓的進行計算過程中,
        // 此時主線程仍然會繼續(xù)執(zhí)行, 下面的 end 就隨之被計算了.
        // 正確的做法應(yīng)該是要保證 t1 和 t2 都計算完畢, 再來計算這個 end 的時間戳.
        long end = System.currentTimeMillis();
        System.out.println("time: " + (end - beg) + " ms");
    }
}

多次運行,結(jié)果如下:

這里發(fā)現(xiàn),由于規(guī)定了線程運行先后時間,導(dǎo)致運行時間大大增長,由此體現(xiàn)了線程并發(fā)運行的優(yōu)勢所在。

這里說明一點:由于線程是搶占式執(zhí)行,所以每次結(jié)果都是不一定的,但誤差會在一定范圍內(nèi)。

二:創(chuàng)建線程的幾個常用方法

2.2 繼承 Thread 類

可以通過繼承 Thread 來創(chuàng)建一個線程類,該方法的好處是 this 代表的就是當(dāng)前線程,不需要通過 Thread.currentThread() 來獲取當(dāng)前線程的引用。

class MyThread extends Thread {

@Override

public void run ()

{ System . out . println ( " 這里是線程運行的代碼 " );

}

}

MyThread t = new MyThread ();

t . start (); // 線程開始運行

2.2 實現(xiàn) Runnable 接口

通過實現(xiàn) Runnable 接口,并且調(diào)用 Thread 的構(gòu)造方法時將 Runnable 對象作為 target 參數(shù)傳入來創(chuàng)建線程對象。 該方法的好處是可以規(guī)避類的單繼承的限制;但需要通過 Thread.currentThread() 來獲取當(dāng)前線程的引用。

class MyRunnable implements Runnable {

@Override

public void run () {

System . out . println ( Thread . currentThread (). getName () + " 這里是線程運行的代碼 " );

}

}

Thread t = new Thread(new MyRunnable());

t.start(); // 線程開始運行

2.3 匿名類創(chuàng)建

// 使用匿名類創(chuàng)建 Thread 子類對象

Thread t1 = new Thread() {

@Override

public void run() {

System.out.println(" 使用匿名類創(chuàng)建 Thread 子類對象 ");

}

};

// 使用匿名類創(chuàng)建 Runnable 子類對象

Thread t2 = new Thread(new Runnable() {

@Override

public void run() {

System.out.println(" 使用匿名類創(chuàng)建 Runnable 子類對象 ");

}

});

// 使用 lambda 表達式創(chuàng)建 Runnable 子類對象

Thread t3 = new Thread(() -> System.out.println(" 使用匿名類創(chuàng)建 Thread 子類對象 "));

Thread t4 = new Thread(() -> {

System.out.println(" 使用匿名類創(chuàng)建 Thread 子類對象 ");

});

三:Thread的幾個常見屬性

代碼如下:

public class ThreadDemo {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    System.out.println(Thread.currentThread().getName() + ": 我還活著");
                    Thread.sleep(1 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName() + ": 我即將死去");
        });
        thread.start();
        System.out.println(Thread.currentThread().getName()
                + ": ID: " + thread.getId());
        System.out.println(Thread.currentThread().getName()
                + ": 名稱: " + thread.getName());
        System.out.println(Thread.currentThread().getName()
                + ": 狀態(tài): " + thread.getState());
        System.out.println(Thread.currentThread().getName()
                + ": 優(yōu)先級: " + thread.getPriority());
        System.out.println(Thread.currentThread().getName()
                + ": 后臺線程: " + thread.isDaemon());
        System.out.println(Thread.currentThread().getName()
                + ": 活著: " + thread.isAlive());
        System.out.println(Thread.currentThread().getName()
                + ": 被中斷: " + thread.isInterrupted());
 
        while (thread.isAlive()) {}
        System.out.println(Thread.currentThread().getName()
                + ": 狀態(tài): " + thread.getState());
    }
}

運行結(jié)果:

由此可見各個關(guān)鍵字的含義,今天的分享就到這里。

記:

最近剛開學(xué),各種事兒,選導(dǎo)師,研一七天都有課,導(dǎo)致時間緊張,希望自己還是可以平衡好學(xué)業(yè)和代碼的關(guān)系吧,謝謝大家支持。

整理不易,大家多多支持。

到此這篇關(guān)于Java 多線程之兩步掌握的文章就介紹到這了,更多相關(guān)Java 多線程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用Java自定義注解實現(xiàn)一個簡單的令牌桶限流器

    使用Java自定義注解實現(xiàn)一個簡單的令牌桶限流器

    限流是在分布式系統(tǒng)中常用的一種策略,它可以有效地控制系統(tǒng)的訪問流量,保證系統(tǒng)的穩(wěn)定性和可靠性,在本文中,我將介紹如何使用Java自定義注解來實現(xiàn)一個簡單的令牌桶限流器,需要的朋友可以參考下
    2023-10-10
  • 高斯混合模型與EM算法圖文詳解

    高斯混合模型與EM算法圖文詳解

    高斯模型就是用高斯概率密度函數(shù)(正態(tài)分布曲線)精確地量化事物,將一個事物分解為若干的基于高斯概率密度函數(shù)(正態(tài)分布曲線)形成的模型
    2021-08-08
  • php上傳文件分類實例代碼

    php上傳文件分類實例代碼

    這篇文章主要介紹了php上傳文件分類實例代碼,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2017-02-02
  • Java中I/O輸入輸出的深入講解

    Java中I/O輸入輸出的深入講解

    Java的I/O技術(shù)可以將數(shù)據(jù)保存到文本文件、二進制文件甚至是ZIP壓縮文件中,以達到永久性保存數(shù)據(jù)的要求,下面這篇文章主要給大家介紹了關(guān)于Java中I/O輸入輸出的相關(guān)資料,需要的朋友可以參考下
    2022-08-08
  • 解決Springboot @WebFilter攔截器未生效問題

    解決Springboot @WebFilter攔截器未生效問題

    這篇文章主要介紹了解決Springboot @WebFilter攔截器未生效問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • java跳出多重循環(huán)的三種實現(xiàn)方式

    java跳出多重循環(huán)的三種實現(xiàn)方式

    文章主要介紹了Java中跳出多重循環(huán)的三種方式:使用`break`配合標簽、在布爾表達式中添加判斷變量、以及使用`try-catch`制造異常,每種方式都有具體的代碼示例,并輸出了相應(yīng)的執(zhí)行結(jié)果
    2025-01-01
  • Java 中的 NoSuchMethodException 異常及解決思路(最新推薦)

    Java 中的 NoSuchMethodException 異常及解決思路(最新推薦)

    NoSuchMethodException異常是Java中使用反射機制時常見的錯誤,它通常由方法名或參數(shù)不匹配、訪問權(quán)限問題、方法簽名不匹配等原因引發(fā),解決方法包括核實方法名及其參數(shù)類型、確認方法訪問權(quán)限、檢查方法簽名和重載問題、確保方法存在于正確的類中,感興趣的朋友一起看看吧
    2025-01-01
  • Spring中的@ControllerAdvice和ResponseBodyAdvice詳解

    Spring中的@ControllerAdvice和ResponseBodyAdvice詳解

    這篇文章主要介紹了Spring中的@ControllerAdvice和ResponseBodyAdvice詳解,@ControllerAdvice作用于@Controller修飾的類里面的所有方法,ResponseBodyAdvice作用于@ResponseBody注解修飾的方法,它可以對這些方法的返回值進行修改,需要的朋友可以參考下
    2024-01-01
  • Java線程池實現(xiàn)帶返回值的方式方法

    Java線程池實現(xiàn)帶返回值的方式方法

    在Java中,線程池是一種重要的多線程處理方式,可以有效管理和重用線程,提高程序的性能和效率,有時候我們需要在多線程處理中獲取線程的返回值,本文將介紹如何使用線程池實現(xiàn)帶返回值的方式方法,需要的朋友可以參考下
    2024-09-09
  • Struts2學(xué)習(xí)筆記(8)-Result常用類型

    Struts2學(xué)習(xí)筆記(8)-Result常用類型

    這篇文章主要介紹Struts2中Result四種常用的類型的用法,希望能給大家做一個參考。
    2016-06-06

最新評論

故城县| 大丰市| 仙桃市| 彩票| 麻城市| 泗洪县| 上栗县| 万年县| 上虞市| 昭苏县| 卓尼县| 邢台县| 礼泉县| 西乌珠穆沁旗| 克拉玛依市| 南开区| 大埔区| 句容市| 博湖县| 万全县| 雅安市| 吴旗县| 闻喜县| 连城县| 阿鲁科尔沁旗| 梁平县| 山阳县| 镇江市| 永定县| 大余县| 闵行区| 达州市| 永顺县| 碌曲县| 阆中市| 桦甸市| 古交市| 忻城县| 尼玛县| 永胜县| 千阳县|