国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

Jadual Kandungan
細(xì)品 Java 中啟動(dòng)線程的正確和錯(cuò)誤方式
前文回顧
start 方法和 run 方法的比較
start 方法分析
start 方法的含義以及注意事項(xiàng)
start 方法源碼分析
源碼
源碼中的流程
run 方法分析
run 方法源碼分析
對于 run 方法的兩種情況
Rumah Java JavaAsas 細(xì)品 Java 中啟動(dòng)線程的正確和錯(cuò)誤方式

細(xì)品 Java 中啟動(dòng)線程的正確和錯(cuò)誤方式

Sep 28, 2020 pm 04:55 PM
java

細(xì)品 Java 中啟動(dòng)線程的正確和錯(cuò)誤方式

細(xì)品 Java 中啟動(dòng)線程的正確和錯(cuò)誤方式

前文回顧

  1. 詳細(xì)分析 Java 中實(shí)現(xiàn)多線程的方法有幾種?(從本質(zhì)上出發(fā))

start 方法和 run 方法的比較

代碼演示:

/**
 * <p>
 * start() 和 run() 的比較
 * </p>
 *
 * @author 踏雪彡尋梅
 * @version 1.0
 * @date 2020/9/20 - 16:15
 * @since JDK1.8
 */public class StartAndRunMethod {    public static void main(String[] args) {        // run 方法演示
        // 輸出: name: main
        // 說明由主線程去執(zhí)行的, 不符合新建一個(gè)線程的本意
        Runnable runnable = () -> {
            System.out.println("name: " + Thread.currentThread().getName());
        };
        runnable.run();        // start 方法演示
        // 輸出: name: Thread-0
        // 說明新建了一個(gè)線程, 符合本意
        new Thread(runnable).start();
    }
}復(fù)制代碼

從以上示例可以分析出以下兩點(diǎn):

  • 直接使用 run 方法不會(huì)啟動(dòng)一個(gè)新線程。(錯(cuò)誤方式)

  • start 方法會(huì)啟動(dòng)一個(gè)新線程。(正確方式)

start 方法分析

start 方法的含義以及注意事項(xiàng)

  • start 方法可以啟動(dòng)一個(gè)新線程。

    • 線程對象在初始化之后調(diào)用了 start 方法之后, 當(dāng)前線程(通常是主線程)會(huì)請求 JVM 虛擬機(jī)如果有空閑的話來啟動(dòng)一下這邊的這個(gè)新線程。
    • 也就是說, 啟動(dòng)一個(gè)新線程的本質(zhì)就是請求 JVM 來運(yùn)行這個(gè)線程。
    • 至于這個(gè)線程何時(shí)能夠運(yùn)行,并不是簡單的由我們能夠決定的,而是由線程調(diào)度器去決定的。
    • 如果它很忙,即使我們運(yùn)行了 start 方法,也不一定能夠立刻的啟動(dòng)線程。
    • 所以說 srtart 方法調(diào)用之后,并不意味這個(gè)方法已經(jīng)開始運(yùn)行了。它可能稍后才會(huì)運(yùn)行,也很有可能很長時(shí)間都不會(huì)運(yùn)行,比如說遇到了饑餓的情況。
    • 這也就印證了有些情況下,線程 1 先掉用了 start 方法,而線程 2 后調(diào)用了 start 方法,卻發(fā)現(xiàn)線程 2 先執(zhí)行線程 1 后執(zhí)行的情況。
    • 總結(jié): 調(diào)用 start 方法的順序并不能決定真正線程執(zhí)行的順序。
    • 注意事項(xiàng)
      • start 方法會(huì)牽扯到兩個(gè)線程。
      • 第一個(gè)就是主線程,因?yàn)槲覀儽仨氁幸粋€(gè)主線程或者是其他的線程(哪怕不是主線程)來執(zhí)行這個(gè) start 方法,第二個(gè)才是新的線程。
      • 很多情況下會(huì)忽略掉為我們創(chuàng)建線程的這個(gè)主線程,不要誤以為調(diào)用了 start 就已經(jīng)是子線程去執(zhí)行了,這個(gè)語句其實(shí)是主線程或者說是父線程來執(zhí)行的,被執(zhí)行之后才去創(chuàng)建新線程。
  • start 方法創(chuàng)建新線程的準(zhǔn)備工作

    • 首先,它會(huì)讓自己處于就緒狀態(tài)。
      • 就緒狀態(tài)指已經(jīng)獲取到除了 CPU 以外的其他資源, 如已經(jīng)設(shè)置了上下文、棧、線程狀態(tài)以及 PC(PC 是一個(gè)寄存器,PC 指向程序運(yùn)行的位置) 等。
    • 做完這些準(zhǔn)備工作之后,就萬事俱備只欠東風(fēng)了,東風(fēng)就是 CPU 資源。
    • 做完準(zhǔn)備工作之后,線程才能被 JVM 或操作系統(tǒng)進(jìn)一步去調(diào)度到執(zhí)行狀態(tài)等待獲取 CPU 資源,然后才會(huì)真正地進(jìn)入到運(yùn)行狀態(tài)執(zhí)行 run 方法中的代碼。
  • 需要注意: 不能重復(fù)的執(zhí)行 start 方法

    • 代碼示例

      /**
      * <p>
      * 演示不能重復(fù)的執(zhí)行 start 方法(兩次及以上), 否則會(huì)報(bào)錯(cuò)
      * </p>
      *
      * @author 踏雪彡尋梅
      * @version 1.0
      * @date 2020/9/20 - 16:47
      * @since JDK1.8
      */public class CantStartTwice {    public static void main(String[] args) {
              Runnable runnable = () -> {
                  System.out.println("name: " + Thread.currentThread().getName());
              };
              Thread thread = new Thread(runnable);        // 輸出: name: Thread-0
              thread.start();        // 輸出: 拋出 java.lang.IllegalThreadStateException
              // 即非法線程狀態(tài)異常(線程狀態(tài)不符合規(guī)定)
              thread.start();
          }
      }復(fù)制代碼
    • 報(bào)錯(cuò)的原因

      • start 一旦開始執(zhí)行,線程狀態(tài)就從最開始的 New 狀態(tài)進(jìn)入到后續(xù)的狀態(tài),比如說 Runnable,然后一旦線程執(zhí)行完畢,線程就會(huì)變成終止?fàn)顟B(tài),而終止?fàn)顟B(tài)永遠(yuǎn)不可能再返回回去,所以會(huì)拋出以上異常,也就是說不能回到初始狀態(tài)了。這里描述的還不夠清晰,讓我們來看看源碼能了解的更透徹。

start 方法源碼分析

源碼

public synchronized void start() {    /**
     * This method is not invoked for the main method thread or "system"
     * group threads created/set up by the VM. Any new functionality added
     * to this method in the future may have to also be added to the VM.
     *
     * A zero status value corresponds to state "NEW".
     */
    // 第一步, 檢查線程狀態(tài)是否為初始狀態(tài), 這里也就是上面拋出異常的原因
    if (threadStatus != 0)        throw new IllegalThreadStateException();    /* Notify the group that this thread is about to be started
     * so that it can be added to the group&#39;s list of threads
     * and the group&#39;s unstarted count can be decremented. */
    // 第二步, 加入線程組
    group.add(this);    boolean started = false;    try {        // 第三步, 調(diào)用 start0 方法
        start0();
        started = true;
    } finally {        try {            if (!started) {
                group.threadStartFailed(this);
            }
        } catch (Throwable ignore) {            /* do nothing. If start0 threw a Throwable then
              it will be passed up the call stack */
        }
    }
}復(fù)制代碼

源碼中的流程

第一步:啟動(dòng)新線程時(shí)會(huì)首先檢查線程狀態(tài)是否為初始狀態(tài), 這也是以上拋出異常的原因。即以下代碼:

if (threadStatus != 0)    throw new IllegalThreadStateException();復(fù)制代碼

其中 threadStatus 這個(gè)變量的注釋如下,也就是說 Java 的線程狀態(tài)最初始(還沒有啟動(dòng))的時(shí)候表示為 0:

/* Java thread status for tools,
 * initialized to indicate thread &#39;not yet started&#39;
 */private volatile int threadStatus = 0;復(fù)制代碼

第二步:將其加入線程組。即以下代碼:

group.add(this);復(fù)制代碼

第三步:最后調(diào)用 start0() 這個(gè) native 方法(native 代表它的代碼不是由 Java 實(shí)現(xiàn)的,而是由 C/C++ 實(shí)現(xiàn)的,具體實(shí)現(xiàn)可以在 JDK 里面看到,了解即可), 即以下代碼:

boolean started = false;try {    // 第三步, 調(diào)用 start0 方法
    start0();
    started = true;
} finally {    try {        if (!started) {
            group.threadStartFailed(this);
        }
    } catch (Throwable ignore) {        /* do nothing. If start0 threw a Throwable then
          it will be passed up the call stack */
    }
}復(fù)制代碼

run 方法分析

run 方法源碼分析

@Overridepublic void run() {    // 傳入了 target 對象(即 Runnable 接口的實(shí)現(xiàn)), 執(zhí)行傳入的 target 對象的 run 方法
    if (target != null) {
        target.run();
    }
}復(fù)制代碼

對于 run 方法的兩種情況

  • 第一種: 重寫了 Thread 類的 run 方法,Threadrun 方法會(huì)失效, 將會(huì)執(zhí)行重寫的 run 方法。

  • 第二種: 傳入了 target 對象(即 Runnable 接口的實(shí)現(xiàn)),執(zhí)行 Thread 的原有 run 方法然后接著執(zhí)行 target 對象的 run 方法。

  • 總結(jié):

    • run 方法就是一個(gè)普通的方法, 上文中直接去執(zhí)行 run 方法也就是相當(dāng)于我們執(zhí)行自己寫的普通方法一樣,所以它的執(zhí)行線程就是我們的主線程。
    • 所以要想真正的啟動(dòng)線程,不能直接調(diào)用 run 方法,而是要調(diào)用 start 方法,其中可以間接的調(diào)用 run 方法。

相關(guān)學(xué)習(xí)推薦:java基礎(chǔ)

Atas ialah kandungan terperinci 細(xì)品 Java 中啟動(dòng)線程的正確和錯(cuò)誤方式. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

Video Face Swap

Video Face Swap

Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Tutorial PHP
1502
276
Bagaimana menangani transaksi di Java dengan JDBC? Bagaimana menangani transaksi di Java dengan JDBC? Aug 02, 2025 pm 12:29 PM

Untuk mengendalikan transaksi JDBC dengan betul, anda mesti terlebih dahulu mematikan mod komit automatik, kemudian melakukan pelbagai operasi, dan akhirnya melakukan atau mengembalikan semula hasilnya; 1. Panggil Conn.SetAutOcommit (palsu) untuk memulakan transaksi; 2. Melaksanakan pelbagai operasi SQL, seperti memasukkan dan mengemaskini; 3. Panggil Conn.Commit () jika semua operasi berjaya, dan hubungi conn.rollback () jika pengecualian berlaku untuk memastikan konsistensi data; Pada masa yang sama, cuba-dengan-sumber harus digunakan untuk menguruskan sumber, mengendalikan pengecualian dengan betul dan menutup sambungan untuk mengelakkan kebocoran sambungan; Di samping itu, adalah disyorkan untuk menggunakan kolam sambungan dan menetapkan mata simpan untuk mencapai rollback separa, dan menyimpan urus niaga sesingkat mungkin untuk meningkatkan prestasi.

Bagaimana untuk bekerja dengan kalendar di Jawa? Bagaimana untuk bekerja dengan kalendar di Jawa? Aug 02, 2025 am 02:38 AM

Gunakan kelas dalam pakej Java.Time untuk menggantikan kelas lama dan kelas kalendar; 2. Dapatkan tarikh dan masa semasa melalui LocalDate, LocalDateTime dan Tempatan Tempatan; 3. Buat tarikh dan masa tertentu menggunakan kaedah (); 4. Gunakan kaedah tambah/tolak untuk meningkatkan dan mengurangkan masa; 5. Gunakan zoneddatetime dan zonid untuk memproses zon waktu; 6. Format dan parse date string melalui DateTimeFormatter; 7. Gunakan segera untuk bersesuaian dengan jenis tarikh lama apabila perlu; pemprosesan tarikh di java moden harus memberi keutamaan untuk menggunakan java.timeapi, yang memberikan jelas, tidak berubah dan linear

Membandingkan kerangka Java: Spring Boot vs Quarkus vs Micronaut Membandingkan kerangka Java: Spring Boot vs Quarkus vs Micronaut Aug 04, 2025 pm 12:48 PM

Pra-formancetartuptimemoryusage, quarkusandmicronautleadduetocompile-timeprocessingandgraalvsupport, withquarkusoftenperforminglightbetterine serverless scenarios.tyvelopecosyste,

Memahami Pelabuhan Rangkaian dan Firewall Memahami Pelabuhan Rangkaian dan Firewall Aug 01, 2025 am 06:40 AM

NetworkPortsandFireWallSworkTogethertoenableCommunicationWileensuringsecurity.1.networkportsarevirtualendpointsNumbered0-655 35, Withwell-KnownportsLike80 (http), 443 (https), 22 (ssh), dan25 (smtp) identitispecificservices.2.portsoperateovertcp (boleh dipercayai, c

Bagaimana pengumpulan sampah berfungsi di java? Bagaimana pengumpulan sampah berfungsi di java? Aug 02, 2025 pm 01:55 PM

Koleksi Sampah Java (GC) adalah mekanisme yang secara automatik menguruskan ingatan, yang mengurangkan risiko kebocoran ingatan dengan menuntut semula objek yang tidak dapat dicapai. 1.GC menghakimi kebolehcapaian objek dari objek akar (seperti pembolehubah stack, benang aktif, medan statik, dan lain -lain), dan objek yang tidak dapat dicapai ditandakan sebagai sampah. 2. Berdasarkan algoritma penandaan tanda, tandakan semua objek yang dapat dicapai dan objek yang tidak ditandai. 3. Mengamalkan strategi pengumpulan generasi: Generasi Baru (Eden, S0, S1) sering melaksanakan MinorGC; Orang tua melakukan kurang tetapi mengambil masa lebih lama untuk melakukan MajorGC; Metaspace Stores Metadata kelas. 4. JVM menyediakan pelbagai peranti GC: SerialGC sesuai untuk aplikasi kecil; ParallelGC meningkatkan throughput; CMS mengurangkan

Membandingkan Java Build Tools: Maven vs Gradle Membandingkan Java Build Tools: Maven vs Gradle Aug 03, 2025 pm 01:36 PM

GradleisthebetterChoiceFormostNewProjectSduetoitSsuperiorflexibility, Prestasi, danModernToolingSupport.1.Gradle'sGroovy/KOT lindslismoreconciseandexpressivethanmaven'sverbosexml.2.GradleOutPerformsMaveninBuildSpeedWithIncrementalcompilation, BuildCac

Pergi dengan contoh penangguhan yang dijelaskan Pergi dengan contoh penangguhan yang dijelaskan Aug 02, 2025 am 06:26 AM

Defer digunakan untuk melaksanakan operasi tertentu sebelum fungsi pulangan, seperti sumber pembersihan; Parameter dinilai dengan serta-merta apabila menangguhkan, dan fungsi-fungsi dilaksanakan mengikut urutan terakhir (LIFO); 1. Pelbagai penahanan dilaksanakan dalam urutan terbalik pengisytiharan; 2. Biasanya digunakan untuk pembersihan yang selamat seperti penutupan fail; 3. Nilai pulangan yang dinamakan boleh diubah suai; 4. Ia akan dilaksanakan walaupun panik berlaku, sesuai untuk pemulihan; 5. Elakkan penyalahgunaan menangguhkan gelung untuk mengelakkan kebocoran sumber; Penggunaan yang betul boleh meningkatkan keselamatan kod dan kebolehbacaan.

Menggunakan jenis html `input` untuk data pengguna Menggunakan jenis html `input` untuk data pengguna Aug 03, 2025 am 11:07 AM

Memilih jenis htmlinput yang betul dapat meningkatkan ketepatan data, meningkatkan pengalaman pengguna, dan meningkatkan kebolehgunaan. 1. Pilih jenis input yang sepadan mengikut jenis data, seperti teks, e -mel, tel, nombor dan tarikh, yang secara automatik boleh menyemak dan menyesuaikan diri dengan papan kekunci; 2. Gunakan HTML5 untuk menambah jenis baru seperti URL, Warna, Julat dan Carian, yang dapat memberikan kaedah interaksi yang lebih intuitif; 3. Gunakan pemegang tempat dan sifat -sifat yang diperlukan untuk meningkatkan kecekapan dan ketepatan pengisian bentuk, tetapi harus diperhatikan bahawa pemegang tempat tidak dapat menggantikan label.

See all articles