【小知識探究系列三】探究stop、destroy、suspend、resume被淘汰的原因

開頭小詩一首以歌頌留在歷史長河的她們:
《題都城南莊》 崔護
去年今日此門中,人面桃花相映紅。人面不知何處去,桃花依舊笑春風。
醒醒,我這是在寫技術文章,怎麼開始吟詩作賦了,罪過。【廢話到此爲止】


我們知道像stop、destroy、suspend、resume這幾種中斷或者阻塞線程的方法在較高java版本中已經被標記上了@Deprecated過期標籤,那麼爲什麼她們曾經登上了java的歷史舞臺而又漸漸的推出了舞臺呢,到底是人性的扭曲還是道德的淪喪呢,亦或是她們不思進取被取而代之呢,如果是被取而代之,那麼取而代之的又是何方人也,本文我們將一探究竟。

一、stop的落幕
首先stop方法的作用是什麼呢,用java源碼中的一句註釋來了解一下:Forces the thread to stop executing.,即強制線程停止執行,'Forces’似乎已經透漏出了stop方法的蠻狠無理。那麼我們再看看java開發者是怎們解釋stop被淘汰了的:

This method is inherently unsafe. Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked (as a natural consequence of the uncheckedThreadDeath exception propagating up the stack). If any of the objects previously protected by these monitors were in an inconsistent state, the damaged objects become visible to other threads, potentially resulting in arbitrary behavior. Many uses of stop should be replaced by code that simply modifies some variable to indicate that the target thread should stop running. The target thread should check this variable regularly, and return from its run method in an orderly fashion if the variable indicates that it is to stop running. If the target thread waits for long periods (on a condition variable, for example), the interrupt method should be used to interrupt the wait.

我們從中可以看出以下幾點:
1.stop這種方法本質上是不安全的
2.使用Thread.stop停止線程會導致它解鎖所有已鎖定的監視器,即直接釋放當前線程已經獲取到的所有鎖,是當前線程直接進入阻塞狀態
我們舉例來看一下上邊提到的兩點:


public static void main(String[] args) throws InterruptedException {
   
   
        Object o1=new Object();
        Object o2=new Object();
        Thread t1=new Thread(()->{
   
   
              synchronized (o1)
              {
   
   
                  synchronized (o2)
                  {
   
   
                      try {
   
   
                          System.out.println("t1獲取到鎖");
                          Thread.sleep(5000);
                          System.out.println("t1結束");
                      } catch (InterruptedException e) {
   
   
                          e.printStackTrace();
                      }
                  }
              }
        });
        t1.start();
        Thread.sleep(1000);
        Thread t2=new Thread(()->{
   
   
            synchronized (o1)
            {
   
   
                synchronized (o2)
                {
   
   
                    try {
   
   
                        System.out.println("t2獲取到鎖");
                        Thread.sleep(5000);
                        System.out.println("t2結束");
                    } catch (InterruptedException e) {
   
   
                        e.printStackTrace();
                    }
                }
            }
        });
        t2.start();
        t1.stop();
    }

運行結果:
在這裏插入圖片描述
可以看到,當線程t1在獲取到o1和o2兩個鎖開始執行,在還沒有執行結束的時候,主線程調用了t1的stop方法中斷了t1的執行,釋放了t1線程獲取到的所有鎖,中斷後t2獲取到了o1和o2鎖,開始執行直到結束,而t1卻夭折在了sleep的時候,sleep後的代碼沒有執行。如果sleep後的代碼是資源釋放、重要業務邏輯等比較重要的代碼的話,亦或是其他線程依賴t1線程的運行結果,那直接中斷將可能造成很嚴重的後果。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章