Rumah  >  Artikel  >  Java  >  Apakah 6 keadaan dan kitaran hayat benang Java?

Apakah 6 keadaan dan kitaran hayat benang Java?

王林
王林ke hadapan
2023-05-02 12:07:061433semak imbas

    1. Keadaan benang (kitaran hayat)

    Sesuatu benang hanya boleh berada dalam satu keadaan pada masa tertentu.

    Benang boleh mempunyai 6 keadaan berikut:

    • Baharu (baru dibuat):

    • Boleh Dijalankan (Boleh Dijalankan ): Utas boleh jalan yang perlu menunggu sumber sistem pengendalian; 🎜>

      Menunggu (menunggu): menunggu status wake-up, menunggu selama-lamanya untuk thread lain untuk bangun; masa Satu utas di mana utas lain menjalankan operasi;
    • Untuk menentukan keadaan semasa benang, anda boleh memanggil kaedah getState
    • Rajah keadaan benang

    • Nota: status kotak bertitik (semua huruf besar Inggeris) ialah status benang Java.

    • 2. Status benang operasi

    • 2.1 Status baru dibuat (BARU)

    bermakna selepas urutan instantiasi selesai, status benang tidak dimulakan.

    Benang boleh dibuat dalam tiga cara

    Timpa kaedah run() kelas Thread

    Apakah 6 keadaan dan kitaran hayat benang Java?

    Laksanakan antara muka Runnable

    Laksanakan antara muka Boleh Panggil

    Contoh mudah meringkaskan tiga cara
      public class Demo {
      
          public static void main(String[] args) throws ExecutionException, InterruptedException {
              /**
               * 1.直接重写run() 或继承Thread类再重写run()
               */
              Thread thread = new Thread() {
                  @Override
                  public void run() {
                      System.out.println("Thread");
                  }
              };
              // 开启线程
              thread.start();
      
              /**
               * 2.lambda、内部类或线程类方式实现Runnable接口,实现run()方法
               * 再交给Thread 类
               */
              Thread runThread = new Thread(() -> {
                  System.out.println("Runnable");
              });
              // 开启线程
              runThread.start();
      
              /**
               * 3.lambda、内部类或线程类方式实现Callable接口,实现call()方法
               * 再交给Thread 类:FutureTask本质也是Runnable实现类
               */
              FutureTask<String> futureTask = new FutureTask<String>(() -> {
                  System.out.println("Callable");
                  return "CallableThread";
              });
              Thread callThread = new Thread(futureTask);
              // 开启线程
              callThread.start();
              // 获取call()方法的返回值
              String s = futureTask.get();
              System.out.println("call()方法的返回值:"+s);
          }
      
      }
    • Jangan tulis semula run() atau call( ) Tidak bermakna untuk membuat instantiat secara langsung urutan yang dibuat oleh kelas Thread;

      Hanya utas yang dibuat dalam kaedah Boleh Panggil boleh memperoleh nilai pulangan benang.
    • 2.2. Keadaan boleh dijalankan (RUNNABLE)

      Keadaan ini merujuk kepada keadaan yang dimasukkan selepas utas membuat instantiat objek dan memanggil kaedah mula(). Benang berada dalam keadaan boleh jalan dan jika terdapat sumber seperti pemproses, atur cara boleh dilaksanakan.
    • Keadaan ini termasuk dua langkah pada

      peringkat sistem pengendalian

      : thread sedia dan thread berjalan, tetapi dalam keadaan thread Java, kedua-dua langkah ini secara kolektif dipanggil keadaan Runnable (runnable).
    Benang bertukar daripada keadaan sedia kepada keadaan berjalan Perkara utama ialah untuk melihat sama ada utas anda telah memperoleh sumber CPU (Sesiapa yang mengambilnya akan menjalankannya, dan jika ia berjaya'). t ambil, tunggu. Oleh kerana hirisan masa CPU (masa pelaksanaan) adalah sangat singkat, kira-kira sepuluh milisaat, masa untuk menukar benang adalah sangat singkat, dan masa untuk keadaan sedia untuk menukar kepada keadaan berjalan juga sangat singkat Keadaan ini hampir tidak kelihatan semasa pembangunan. Perubahan, jadi di Jawa, kedua-duanya dianggap sebagai keseluruhan, memfokuskan pada sama ada benang boleh dijalankan dan membezakannya daripada negeri lain, seterusnya memudahkan pembangunan benang. Jika program anda perlu dijalankan untuk masa yang lama (seperti menulis gelung tak terhingga) dan pelaksanaan tidak selesai dalam sekeping masa CPU, maka utas anda perlu merebut kepingan masa CPU seterusnya Hanya selepas ia telah mencapainya ia terus melaksanakan program Jika ia belum merebutnya, ia boleh terus melaksanakan program Kemudian anda perlu terus merebut sehingga pelaksanaan program dalam utas selesai.

    Malah, anda sepatutnya melihat senario ini sebelum ini, contohnya, apabila berbilang utas melaksanakan program yang sama dan mencetak log ke fail yang sama, log urutan yang berbeza akan dicampur bersama, yang tidak sesuai untuk. soalan penyelesaian masalah. Kaedah biasa untuk menyelesaikan masalah ini ialah: pertama, cetak log ke fail yang berbeza dalam benang yang berbeza kedua, simpan maklumat log ke dalam objek rentetan, dan cetak maklumat log ke fail sekaligus pada akhir program. Kaedah kedua ialah menggunakan kepingan masa CPU untuk melengkapkan pencetakan maklumat log.

    Nota: Program ini hanya boleh memanggil kaedah mula() pada utas dalam keadaan yang baru dibuat Jangan panggil kaedah mula() pada utas dalam

    keadaan bukan baru dibuat

    . Ini akan menyebabkan pengecualian IllegalThreadStateException.

    2.3. Keadaan disekat (DISEKAT)

    Benang berada dalam keadaan disekat semasa

    menunggu monitor kunci

    . Satu benang memperoleh kunci tetapi tidak melepaskannya.

    Keadaan disekat hanya wujud di bawah akses serentak oleh berbilang rangkaian, yang berbeza daripada dua jenis sekatan yang terakhir yang disebabkan oleh urutan itu sendiri memasuki "menunggu".

    Masukkan keadaan

    Masukkan blok/kaedah kod disegerakkan

    Kunci tidak diperoleh

    Status keluar

    • Mendapat kunci monitor

    • 2.4 nyatakan (MENUNGGU)

      Seluruh prosesnya adalah seperti ini: utas memperoleh kunci objek terlebih dahulu dalam kaedah penyegerakan objek; apabila kaedah tunggu dilaksanakan, utas akan melepaskan kunci objek, dan utas diletakkan Masukkan baris gilir menunggu objek ini; tunggu untuk benang lain memperoleh kunci objek yang sama, dan kemudian bangunkan benang dalam baris gilir menunggu objek melalui kaedah notify() atau notifyAll().
    Daripada keseluruhan proses, kita boleh tahu bahawa kaedah

    tunggu (), notify () dan notifyAll () perlu mendapatkan kunci sebelum utas boleh terus dilaksanakan, jadi ketiga-tiga ini kaedah diperlukan Letakkannya dalam blok/kaedah kod yang disegerakkan untuk pelaksanaan, jika tidak pengecualian akan dilaporkan: java.lang.IllegalMonitorStateException.

    在同步代码块中,线程进入WAITING 状态时,锁会被释放,不会导致该线程阻塞。反过来想下,如果锁没释放,那其他线程就没办法获取锁,也就没办法唤醒它。

    进入状态

    • object.wait()

    • thread.join()

    • LockSupport.park()

    退出状态

    • object.notify()

    • object.notifyall()

    • LockSupport.unpark()

    2.5.计时等待状态(TIMED_WAITING)

    一般是计时结束就会自动唤醒线程继续执行后面的程序,对于Object.wait(long) 方法还可以主动通知唤醒。

    注意:Thread类下的sleep() 方法可以放在任意地方执行;而wait(long) 方法和wait() 方法一样,需要放在同步代码块/方法中执行,否则报异常:java.lang.IllegalMonitorStateException。

    进入状态

    • Thread.sleep(long)

    • Object.wait(long)

    • Thread.join(long)

    • LockSupport.parkNanos(long)

    • LockSupport.parkNanos(Object blocker, long nanos)

    • LockSupport.parkUntil(long)

    • LockSupport.parkUntil(Object blocker, long deadline)

    注:blocker 参数为负责此线程驻留的同步对象。

    退出状态

    • 计时结束

    • LockSupport.unpark(Thread)

    • object.notify()

    • object.notifyall()

    2.6.终止(TERMINATED)

    线程执行结束

    • run()/call() 执行完成

    • stop()线程

    • 错误或异常>>意外死亡

    stop() 方法已弃用。

    3.查看线程的6种状态

    通过一个简单的例子来查看线程出现的6种状态。

    案例

    public class Demo3 {
        private static Object object ="obj";
        
        public static void main(String[] args) throws InterruptedException {
    
            Thread thread0 = new Thread(() -> {
                try {
                    // 被阻塞状态(BLOCKED)
                    synchronized (object){
                        System.out.println("thread0 进入:等待唤醒状态(WAITING)");
                        object.wait();
                        System.out.println("thread0 被解除完成:等待唤醒状态(WAITING)");
                    }
                    System.out.println("thread0 "+Thread.currentThread().getState());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            // 新创建状态(NEW)
            System.out.println(thread0.getName()+":"+thread0.getState());
    
            Thread thread1 = new Thread(() -> {
                try {
                    System.out.println("thread1 进入:计时等待状态(TIMED_WAITING)");
                    Thread.sleep(2);
                    System.out.println("thread1 出来:计时等待状态(TIMED_WAITING)");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 被阻塞状态(BLOCKED)
                synchronized (object){
                    System.out.println("thread1 解除:等待唤醒状态(WAITING)");
                    object.notify();
                    System.out.println("thread1 解除完成:等待唤醒状态(WAITING)");
                }
                System.out.println("thread1 "+Thread.currentThread().getState());
            });
            // 新创建状态(NEW)
            System.out.println(thread1.getName()+":"+thread1.getState());
    
            printState(thread0);
            printState(thread1);
    
            // 可运行状态(RUNNABLE)
            thread0.start();
            // 可运行状态(RUNNABLE)
            thread1.start();
    
        }
        
        
        // 使用独立线程来打印线程状态
        private static void printState(Thread thread) {
            new Thread(()->{
                while (true){
                    System.out.println(thread.getName()+":"+thread.getState());
                    if (thread.getState().equals(Thread.State.TERMINATED)){
                        System.out.println(thread.getName()+":"+thread.getState());
                        break;
                    }
                }
            }).start();
        }
    }

    执行结果:简化后的输出结果

    Thread-0:NEW
    Thread-1:NEW
    Thread-0:RUNNABLE
    Thread-1:RUNNABLE
    thread0 进入:等待唤醒状态(WAITING)
    Thread-1:BLOCKED
    thread1 进入:计时等待状态(TIMED_WAITING)
    Thread-0:BLOCKED
    Thread-0:WAITING
    ……
    Thread-0:WAITING
    Thread-1:BLOCKED
    Thread-1:TIMED_WAITING
    ……
    Thread-1:TIMED_WAITING
    Thread-1:BLOCKED
    ……
    Thread-1:BLOCKED
    Thread-0:WAITING
    ……
    Thread-0:WAITING
    thread1 出来:计时等待状态(TIMED_WAITING)
    Thread-0:WAITING
    Thread-1:BLOCKED
    thread1 解除:等待唤醒状态(WAITING)
    Thread-1:BLOCKED
    Thread-0:WAITING
    Thread-0:BLOCKED
    thread1 解除完成:等待唤醒状态(WAITING)
    Thread-1:BLOCKED
    thread1 RUNNABLE
    Thread-0:BLOCKED
    Thread-1:TERMINATED
    thread0 被解除完成:等待唤醒状态(WAITING)
    Thread-0:BLOCKED
    thread0 RUNNABLE
    Thread-0:TERMINATED

    Apakah 6 keadaan dan kitaran hayat benang Java?

    最终的执行结果如图。

    注意:因为案例中使用了独立线程来打印不同线程的状态,会出现状态打印稍微延迟的情况。

    Atas ialah kandungan terperinci Apakah 6 keadaan dan kitaran hayat benang Java?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

    Kenyataan:
    Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam
    Artikel sebelumnya:Apakah itu Corak Pembina JavaArtikel seterusnya:Apakah itu Corak Pembina Java