欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java線程生命周期的終止與復(fù)位

 更新時(shí)間:2022年07月03日 09:38:21   作者:??益發(fā)不可收拾????  
這篇文章主要介紹了Java線程生命周期的終止與復(fù)位,Java的線程狀態(tài)描述放在Thread類里面的枚舉類State中.總共包含了6中狀態(tài),具體詳情需要的小伙伴可以參考一下文章描述

Thread生命周期

生命周期概述

Java的線程狀態(tài)描述放在Thread類里面的枚舉類State中.總共包含了6中狀態(tài)(從出生到死亡)。

public enum State {
    /**
     * 尚未啟動(dòng)的線程的線程狀態(tài) (沒(méi)有start)
     */
    NEW,

    /**
     * 可運(yùn)行線程的線程狀態(tài),是可以運(yùn)行的線程狀態(tài)(并不是在運(yùn)行)
     * 這個(gè)狀態(tài)在Java虛擬機(jī)中進(jìn)行,但它可能等待來(lái)自操作系統(tǒng)的其他資源,比如CPU。
     * 內(nèi)部包含了兩個(gè)狀態(tài) 【RUNNING】,【READY】這兩個(gè)狀態(tài)是可以互相流轉(zhuǎn)的
     * 調(diào)用了start后線程就處于 READY 狀態(tài) ,等待操作系統(tǒng)分配CPU時(shí)間片,分配后進(jìn)入 RUNNING 狀態(tài)。
     * 當(dāng)調(diào)用 yield() 方法后,只是謙讓的允許當(dāng)前線程讓出 CPU ,但是不一定讓,由操作系統(tǒng)決定,如果讓      * 了當(dāng)前線程就會(huì)進(jìn)入 READY 狀態(tài),等待系統(tǒng)分配CPU時(shí)間片再次進(jìn)入 RUNNING 狀態(tài)。
     */
    RUNNABLE,

    /**
     * 阻塞狀態(tài)。
     * 線程阻塞,等待監(jiān)視器鎖的狀態(tài),獲取監(jiān)視器鎖后會(huì)進(jìn)入 RUNNABLE  狀態(tài)
     * 當(dāng)發(fā)生線程鎖競(jìng)爭(zhēng)狀態(tài)下,沒(méi)有獲取到鎖的線程會(huì)被掛起進(jìn)入阻塞狀態(tài),比如synchronized鎖。
     */
    BLOCKED,

    /**
     * 等待線程的線程狀態(tài)
     * 線程調(diào)用以下方法會(huì)處于等待狀態(tài):Object.wait()不超時(shí)、Thread.join()不超時(shí)等方法
     * 一個(gè)處于等待狀態(tài)的線程正在等待另一個(gè)線程執(zhí)行特定動(dòng)作,例如:
     * 一個(gè)線程調(diào)用了Object.wait()方法在一個(gè)對(duì)象上正在等待另一個(gè)線程調(diào)用Object.nofify()或者
     * Object.nofifyAll()方法開(kāi)啟那個(gè)對(duì)象
     * 一個(gè)調(diào)用了Thread.join()方法的線程正在等待指定線程終止
     */
    WAITING,

    /**
     * 具有指定等待時(shí)間的等待線程的線程狀態(tài),調(diào)用一下方法會(huì)處于這個(gè)狀態(tài): Object.wait() 超時(shí)、          * Thread.join()超時(shí) Thread.sleep(long) 等方法 
     */
    TIMED_WAITING,

    /**
     * 已終止線程的線程狀態(tài)
     * 線程執(zhí)行完畢或者發(fā)生異常終止執(zhí)行
     */
    TERMINATED;
}

線程生命周期流程圖

線程生命周期測(cè)試

public class ThreadStatusDemo {
    public static void main(String[] args) throws InterruptedException {
        // 測(cè)試 NEW RUNNABLE TERMINATED
        Thread terminated_thread = new Thread(() -> {
            long start = System.currentTimeMillis();
            // 運(yùn)行三秒 ,打印TERMINATED_THREAD線程runnable狀態(tài)
            while (System.currentTimeMillis()-start<3000){}
        }, "TERMINATED_THREAD");
        // NEW
        Thread.State state = terminated_thread.getState();
        System.out.println(terminated_thread.getName()+" :state = " + state);

        terminated_thread.start();
        TimeUnit.SECONDS.sleep(1);
        // RUNNABLE
        Thread.State state1 = terminated_thread.getState();
        System.out.println(terminated_thread.getName()+"state1 = " + state1);

        TimeUnit.SECONDS.sleep(5);
        Thread.State state2 = terminated_thread.getState();
        // TERMINATED
        System.out.println(terminated_thread.getName()+"state2 = " + state2);

        // RUNNABLE
        new Thread(() -> {
            while (true) {

            }
        }, "Runnle_Thread").start();
        // TIMED_WAITING
        new Thread(() -> {
            while (true) {
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "Time_Waiting_Thread").start();
        // WAITING
        new Thread(() -> {
            while (true) {
                synchronized (ThreadStatusDemo.class) {
                    try {
                        ThreadStatusDemo.class.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }, "Waiting_Thread").start();

        // 這兩個(gè)看誰(shuí)先搶占到cpu獲得鎖,另一個(gè)就blocked
        // timed_waiting
        new Thread(new BlockedDemo(), "Blocke01_Thread").start();
        // blocked
        new Thread(new BlockedDemo(), "Blocke02_Thread").start();
    }
    static class BlockedDemo extends Thread {
        @Override
        public void run() {
            synchronized (BlockedDemo.class) {
                while (true) {
                    try {
                        TimeUnit.SECONDS.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

啟動(dòng)線程

java中的啟動(dòng)

Java啟動(dòng)一個(gè)線程調(diào)用start方法,start方法內(nèi)部調(diào)用了 start0()native方法。

public synchronized void start() {
    . . .
    boolean started = false;
    try { 
        // 調(diào)用native方法
        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 */
        }
    }
}

這個(gè)測(cè)試是為了驗(yàn)證上圖的正確性,只貼了部分.

Hotspot中的啟動(dòng)

查看指引:

 在jvm.cpp找到JVM_StartThread方法。發(fā)現(xiàn)是先創(chuàng)建個(gè) JavaThread作為本地線程然后啟動(dòng)這個(gè)本地線程(借助os【thread.cpp】,因?yàn)閖vm是跨平臺(tái)的,這里是以linux-os為示例)

JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))
  JVMWrapper("JVM_StartThread");
  JavaThread *native_thread = NULL;
  bool throw_illegal_thread_state = false;
  {
    MutexLocker mu(Threads_lock);

    if (java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) != NULL) {
      throw_illegal_thread_state = true;
    } else {
      jlong size =
             java_lang_Thread::stackSize(JNIHandles::resolve_non_null(jthread));
      size_t sz = size > 0 ? (size_t) size : 0;
      // 先創(chuàng)建一個(gè)JavaThread
      native_thread = new JavaThread(&thread_entry, sz);
      if (native_thread->osthread() != NULL) {
        native_thread->prepare(jthread);
      }
    }
  }
  if (throw_illegal_thread_state) {
    THROW(vmSymbols::java_lang_IllegalThreadStateException());
  }
  assert(native_thread != NULL, "Starting null thread?");
  if (native_thread->osthread() == NULL) {
    delete native_thread;
    if (JvmtiExport::should_post_resource_exhausted()) {
      JvmtiExport::post_resource_exhausted(
        JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_THREADS,
        "unable to create new native thread");
    }
    THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(),
              "unable to create new native thread");
  }
  // 然后啟動(dòng)這個(gè)本地線程 thread.cpp
  Thread::start(native_thread);
JVM_END

JavaThread 創(chuàng)建線程:

JavaThread::JavaThread(ThreadFunction entry_point, size_t stack_sz) :
  Thread()
#if INCLUDE_ALL_GCS
  , _satb_mark_queue(&_satb_mark_queue_set),
  _dirty_card_queue(&_dirty_card_queue_set)
#endif // INCLUDE_ALL_GCS
{
  if (TraceThreadEvents) {
    tty->print_cr("creating thread %p", this);
  }
  initialize();
  _jni_attach_state = _not_attaching_via_jni;
  set_entry_point(entry_point);
  os::ThreadType thr_type = os::java_thread;
  thr_type = entry_point == &compiler_thread_entry ? os::compiler_thread :
                                                     os::java_thread
// 調(diào)用os(操作系統(tǒng))創(chuàng)建個(gè)線程
  os::create_thread(this, thr_type, stack_sz);
  _safepoint_visible = false;
   . . .
}

thread.cpp 啟動(dòng)線程:

// tips: 啟動(dòng)線程的方法
void Thread::start(Thread* thread) {
  trace("start", thread);
  // Start is different from resume in that its safety is guaranteed by context or
  // being called from a Java method synchronized on the Thread object.
  if (!DisableStartThread) {
    if (thread->is_Java_thread()) {
      // Initialize the thread state to RUNNABLE before starting this thread.
      // Can not set it after the thread started because we do not know the
      // exact thread state at that time. It could be in MONITOR_WAIT or
      // in SLEEPING or some other state.
      // tips:啟動(dòng)之后設(shè)置線程的狀態(tài)為 可運(yùn)行狀態(tài) RUNNABLE
      java_lang_Thread::set_thread_status(((JavaThread*)thread)->threadObj(),
                                          java_lang_Thread::RUNNABLE);
    }
    // 借助操作系統(tǒng)啟動(dòng)線程
    os::start_thread(thread);
  }
}

線程中斷與復(fù)位

不要使用stop方法

線程的終止不要簡(jiǎn)單的調(diào)用 stop方法,這個(gè)方法和其他的線程控制方法(suspend,resume)一樣都是過(guò)期了不建議使用的,這些方法都是不安全的。 例如stop()方法在結(jié)束一個(gè)線程的時(shí)候并不保證線程資源的正常釋放,因此可能導(dǎo)致出現(xiàn)一些不確定的狀態(tài)。 按照人類邏輯來(lái)理解:T1線程調(diào)用方法修改T2線程的狀態(tài),但是T2現(xiàn)在在做什么T1是不清楚的,所以強(qiáng)制他關(guān)閉就是不安全的,就好比在Linux中使用 kill -9 殺掉一個(gè)進(jìn)程。

使用interrupt方法

interrupt()方法只是修改了被中斷線程的中斷標(biāo)志 ,并沒(méi)有做什么過(guò)分的事兒。就像平時(shí)寫(xiě)代碼的時(shí)候修改某對(duì)象的標(biāo)志,對(duì)象自己通過(guò)標(biāo)志類決定執(zhí)行什么邏輯。這里也是一樣,interrupt()方法修改中斷標(biāo)志,被中斷的線程,自己決定做什么事兒(中斷或者不中斷都是被中斷線程自己決定的,外部只是通知他,不是強(qiáng)迫他)。追一下源碼。

1.Java調(diào)用interrupt方法 

2.通過(guò)指引找到 jvm.cpp#JVM_Interrupt方法

thread.cpp interrupt 借用操作系統(tǒng)。直接通過(guò)系統(tǒng)調(diào)用 interrupt
void Thread::interrupt(Thread* thread) {
  trace("interrupt", thread);
  debug_only(check_for_dangling_thread_pointer(thread);)
  // tips: 調(diào)用操作系統(tǒng)的interrupt方法
  os::interrupt(thread);
}

這里還是以os_linux.cpp為例最終調(diào)用osthread的set_interrupted修改狀態(tài) 

這里就印證了上方的 Thread.interrupt()只是修改了線程的一個(gè)標(biāo)志位 ,并沒(méi)有做什么過(guò)分的事兒。

線程的復(fù)位

interruptedisInterrupted

這兩個(gè)放在一起是因?yàn)樗麄兊讓佣际钦{(diào)用的同一個(gè)native方法isInterrupted()只是給了不同的入?yún)ⅰ?再就是,有過(guò)面試官問(wèn)到他兩的區(qū)別,所以干脆放在一起。首先說(shuō)結(jié)論 ,isInterrupted()會(huì)返回線程的中斷狀態(tài),interrupted()不僅會(huì)返回中斷狀態(tài),而且如果線程處于狀態(tài)狀態(tài)還會(huì)將線程終端狀態(tài)復(fù)位(清除中斷狀態(tài))。

os_linux.cpp的is_interrupted()方法印證了上面說(shuō)的isInterrupted()會(huì)返回線程的中斷狀態(tài),interrupted()不僅會(huì)返回中斷狀態(tài),而且如果線程處于狀態(tài)狀態(tài)還會(huì)將線程終端狀態(tài)復(fù)位(清除中斷狀態(tài))。

其他的線程復(fù)位

Java中只要拋出了InnterruptException異常的方法都對(duì)線程進(jìn)行了復(fù)位。先理順下為什么要這么做:查看下基本上拋出InnterruptException異常的方法都是線程阻塞方法,比如sleep(),wait(),join()。這類方法執(zhí)行后線程會(huì)處于TIMED_WAITING或者WAITING狀態(tài),處于這類狀態(tài)的線程是不受控的(線程喪失了對(duì)自己的主導(dǎo),需要其他的線程喚醒,或者阻塞時(shí)間到達(dá)才能擁有自己的主導(dǎo)權(quán)),這個(gè)時(shí)候線程中斷,線程自己卻沒(méi)辦法處理。甚至可能永遠(yuǎn)等不到釋放而無(wú)法執(zhí)行中斷。所以,在線程是中斷狀態(tài)下,執(zhí)行方法讓線程阻塞,就要拋出一個(gè)異常告訴外界 ,我現(xiàn)在是阻塞狀態(tài),并且將中斷標(biāo)記復(fù)位,方便外界進(jìn)行處理(例如中斷線程的執(zhí)行或者繼續(xù)阻塞方法),相當(dāng)于給了外界一個(gè)改變線程狀態(tài)的入口。 以sleep()為例追蹤下源碼:

通過(guò)指引找到 jcm.cpp#JVM_Sleep

方法入口就直接判斷線程的中斷狀態(tài)了 ,is_interrupted()上面介紹過(guò)了,參數(shù)為true就是清除中斷標(biāo)志并且返回清除之前的中斷狀態(tài)。這里線程是中斷狀態(tài)的就直接拋出 InnterruptException sleep interrupted異常了。

到此這篇關(guān)于Java線程生命周期的終止與復(fù)位的文章就介紹到這了,更多相關(guān)Java線程生命周期內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring Cloud Gateway不同頻率限流的解決方案(每分鐘,每小時(shí),每天)

    Spring Cloud Gateway不同頻率限流的解決方案(每分鐘,每小時(shí),每天)

    SpringCloud Gateway 是 Spring Cloud 的一個(gè)全新項(xiàng)目,它旨在為微服務(wù)架構(gòu)提供一種簡(jiǎn)單有效的統(tǒng)一的 API 路由管理方式。這篇文章主要介紹了Spring Cloud Gateway不同頻率限流(每分鐘,每小時(shí),每天),需要的朋友可以參考下
    2020-10-10
  • 關(guān)于 Java 的數(shù)據(jù)結(jié)構(gòu)鏈表

    關(guān)于 Java 的數(shù)據(jù)結(jié)構(gòu)鏈表

    這篇文章主要介紹了關(guān)于 Java 的數(shù)據(jù)結(jié)構(gòu)鏈表的相關(guān)資料,需要的朋友可以參考下面文章內(nèi)容
    2021-09-09
  • Spring自動(dòng)掃描無(wú)法掃描jar包中bean的解決方法

    Spring自動(dòng)掃描無(wú)法掃描jar包中bean的解決方法

    在日常開(kāi)發(fā)中往往會(huì)對(duì)公共的模塊打包發(fā)布,然后調(diào)用公共包的內(nèi)容。然而,最近對(duì)公司的公共模塊進(jìn)行整理發(fā)布后。spring卻無(wú)法掃描到相應(yīng)的bean,下面這篇文章主要給大家介紹了關(guān)于Spring自動(dòng)掃描時(shí)無(wú)法掃描jar包中bean的解決方法,需要的朋友可以參考下。
    2017-06-06
  • Java中高效的判斷數(shù)組中某個(gè)元素是否存在詳解

    Java中高效的判斷數(shù)組中某個(gè)元素是否存在詳解

    相信大家在操作Java的時(shí)候,經(jīng)常會(huì)要檢查一個(gè)數(shù)組(無(wú)序)是否包含一個(gè)特定的值?這是一個(gè)在Java中經(jīng)常用到的并且非常有用的操作。同時(shí),這個(gè)問(wèn)題在Stack Overflow中也是一個(gè)非常熱門(mén)的問(wèn)題。本文將分析幾種常見(jiàn)用法及其時(shí)間成本,有需要的朋友們可以參考借鑒。
    2016-11-11
  • Spring中propagation的傳播機(jī)制詳解

    Spring中propagation的傳播機(jī)制詳解

    這篇文章主要介紹了Spring中propagation的傳播機(jī)制詳解,要搞懂事務(wù)的傳播機(jī)制,那么就要明白邏輯事務(wù)中各個(gè)事務(wù)的關(guān)系,才能徹底理解事務(wù)傳播特性,在Spring事務(wù)中,各個(gè)邏輯事務(wù)的關(guān)系可以是并列、覆蓋或包含,需要的朋友可以參考下
    2023-12-12
  • 一文帶你了解Spring中@Enable開(kāi)頭注解的使用

    一文帶你了解Spring中@Enable開(kāi)頭注解的使用

    前面的文章給大家介紹?Spring?的重試機(jī)制的時(shí)候有提到過(guò)?Spring?有很多?@Enable?開(kāi)頭的注解,平時(shí)在使用的時(shí)候也沒(méi)有注意過(guò)為什么會(huì)有這些注解,今天就給大家介紹一下
    2022-09-09
  • Java讀寫(xiě)Windows共享文件夾的方法實(shí)例

    Java讀寫(xiě)Windows共享文件夾的方法實(shí)例

    本篇文章主要介紹了Java讀寫(xiě)Windows共享文件夾的方法實(shí)例,具有一定的參考價(jià)值,有興趣的同學(xué)可以了解一下。
    2016-11-11
  • 最新評(píng)論