1. 程式人生 > >多執行緒——(一):暫停、恢復、停止執行緒較好的方式,sleep/wait/yield區別

多執行緒——(一):暫停、恢復、停止執行緒較好的方式,sleep/wait/yield區別

不推薦的

大家都知道:suspend()、resume()、stop()這些方法已經被廢棄了。suspend()、resume()如果使用不當,容易造成公共的同步物件資源的獨佔以及導致資料不同步。用官網的話說:

This method has been deprecated, as it is inherently deadlock-prone. If the target thread holds a lock on the monitor protecting a critical system resource when it is suspended, no thread can access this resource until the target thread is resumed. If the thread that would resume the target thread attempts to lock this monitor prior to calling resume, deadlock results. Such deadlocks typically manifest themselves as “frozen” processes.

在JDK1.2以前的版本如果要實現執行緒的暫停、恢復和停止的方法分別是suspend()、resume()、stop()。但是從JDK1.2以後這些方法已經被遺棄,因為它們有可能造成嚴重的系統錯誤和異常。
首先suspend()方法不會釋放執行緒所佔用的資源。如果使用該方法將某個執行緒掛起,則可能會使其他等待資源的執行緒死鎖。而resume()方法本身並無問題,但是不能獨立於suspend()方法存在。
其次呼叫stop()可能會導致嚴重的系統故障。因為該方法會使執行緒立刻中斷指令執行,不管這段方法是否執行完畢。如果這個執行緒正在做重要的操作,對程式的執行起著支撐作用,這時如果突然中斷其執行則會導致系統崩潰。

其他的方法

暫停:

有必要先學習下sleep()、wait()、yeild()的區別:

sleep()與wait()——

區別:
1.wait()是用於執行緒間通訊的,而sleep()是用於短時間暫停當前執行緒。
2.wait方法應在同步程式碼塊中呼叫,但是sleep方法不一定需要。【換句話說就是:wait方法是針對一個被同步程式碼塊加鎖的物件,而sleep是針對一個執行緒。】
3.其中,sleep()方法是屬於Thread類中的。而wait()方法是屬於Object類中的。
sleep()方法導致了程式暫停執行指定的時間,讓出cpu等資源給其他執行緒,但是並不會釋放物件鎖

,它的監控狀態依然保持著,當指定的時間到了又會自動恢復執行狀態。sleep是生物鐘,自己醒。
4.而當呼叫wait()方法的時候,執行緒會放棄物件鎖,進入等待此物件的等待鎖定池,以便其他正在等待該資源的執行緒得到該資源進而執行,只有其他執行緒呼叫了notify()(或notifyAll)方法,呼叫wait()的執行緒才會解除wait狀態,可以去參與競爭同步資源鎖,進而得到執行。不呼叫notify的話,之前呼叫wait的執行緒將一直掛起,測試可以發現main執行緒也一直不會結束。
wait是鬧鐘,叫醒睡著的人
5.【比如說有class A,Thread1和Thread2。當一個執行緒呼叫了wait方法,如果沒有其他執行緒呼叫notify方法,它將失去“復活”的機會,一直處於掛起狀態】

程式碼:yield+時間實現暫停:(感覺意義不大)

package per.wanghai.threadcontrol;

/**
 * @author 王海
 * @package per.wanghai.threadcontrol
 * @description 使用yield和時間片實現執行緒掛起
 * @Date 2018/2/25 19:42
 * @Version V1.0
 */
public class UseYieldToSuspend{
    private static class MyThread implements Runnable{
        private int yieldTime = 12000;
        @Override
        public void run(){
            int count=10;
            Long beginTime = System.currentTimeMillis();
            while (System.currentTimeMillis()-beginTime < this.yieldTime){
//            Thread.yield();
                count++;
            }
            System.out.println("count的值為-----" + count);
        }
    }

    public static void main(String[] args) {
        new Thread(new MyThread(),"xianc1");
        MyThread thread = new MyThread();
        thread.run();
    }
}

yield補充:

yield方法會臨時暫停當前正在執行的執行緒,來讓有同樣優先順序的正在等待的執行緒有機會執行。如果沒有正在等待的執行緒,或者所有正在等待的執行緒的優先順序都比較低,那麼該執行緒會繼續執行。執行了yield方法的執行緒什麼時候會繼續執行由執行緒排程器來決定,不同的廠商可能有不同的行為。yield方法不保證當前的執行緒會暫停或者停止,(也就是說不保證時效),但是可以保證當前執行緒在呼叫yield方法時會放棄CPU
驗證:
i): 驗證此方法可行
去掉yield,執行15秒:

這裡寫圖片描述
暫停13.5秒時:
這裡寫圖片描述
暫停5秒時:
這裡寫圖片描述
ii): 驗證yield自身放棄cpu等資源的時間是不定的

long count = 0L;
            long beginTime = System.currentTimeMillis();
            /*while (System.currentTimeMillis() - beginTime < allTime) {
                if (System.currentTimeMillis() - beginTime < yieldTime) {
                    Thread.yield();
                    System.out.println(this.);
                }
                count++;
            }*/
            for (int i = 0; i < 100000; i++){
                Thread.yield();
                count = count + i +1;
            }
            System.out.println("用時為-----" +(System.currentTimeMillis() - beginTime) + "毫秒" + count);

嘗試了3次,用時分別為(ms):128;282;4095

恢復

sleep睡眠結束;notify()/notifyAll();yeild時間片用完靠排程器恢復

停止

stop()方法由於可能會讓一些重要的工作得不到完成而不建議使用,另外stop()釋放鎖還可能會導致資料不一致。
1.退出標誌,正常結束
2.使用interrupt結合拋異常或者break語句:
注意:
i):如果interrupt()方法用作for迴圈和if判斷中,使用break時需要注意break之後是否還有執行語句,比如:

for(int i = 0; i<10000; i++){
    if(this.interrupted()){
        System.out.println("停止狀態了,執行緒退出了!");
        // 這裡使用break後,下面照常會列印時間
        break;
    }
    System.out.println("我的本意是:只要執行緒不是停止狀態,我就列印當前時間" + currentTime);
}

此時可以使用拋異常來解決bug——將break語句替換為
throw new InterruptedException();

ii):interrupted()方法和isInterrupted()方法的區別

控制變數,綜合實現暫停、恢復、停止

參考

相關推薦

執行——暫停恢復停止執行方式sleep/wait/yield區別

不推薦的 大家都知道:suspend()、resume()、stop()這些方法已經被廢棄了。suspend()、resume()如果使用不當,容易造成公共的同步物件資源的獨佔以及導致資料不同步。用官網的話說: This method has

Java執行執行基礎及建立

(一)、執行緒的生命週期 新建狀態: 使用 new 關鍵字和 Thread 類或其子類建立一個執行緒物件後,該執行緒物件就處於新建狀態。它保持這個狀態直到程式 start() 這個執行緒。 就緒狀態: 當執行緒物件呼叫了start()方法之後,該執行緒就進入就緒

Java執行執行與程序

1.執行緒和程序 1.1 程序 程序是作業系統的概念,我們執行的一個TIM.exe就是一個程序。 程序(Process)是計算機中的程式關於某資料集合上的一次執行活動,是系統進行資源分配和排程的基本單位,是作業系統結構的基礎。在早期面向程序設計的計算機結構中,程序是程式的基本執行實體;在當代面向執行緒設計

執行理論知識

目錄 一、作業系統執行緒理論 1)執行緒概念的引入背景 程序 有了程序為什麼要有執行緒 執行緒的出現 2)程序和執行緒的關係 3)執行緒的特點 4)使用執行緒的實際場景 5)記憶體中的執行緒 6)使用者級執行緒和核心級執行緒(瞭解) 使用者級執行緒 核

QT執行執行

執行緒之間共享資料,但又單獨執行;     QT執行緒QThread是平臺無關的;     通常主執行緒從main開始執行,而在主執行緒中建立其他執行緒,其他執行緒派生於QThread; 1、執行緒優先順序 總共8個優先順序:執行緒優先順序從上到下越來越高。 Cons

MFC文件檢視中獲取文件指標

多文件系列 MFC多文件(一):檢視中獲取文件指標 MFC多文件(二):文件中獲取檢視指標 MFC多文件(三):文件與檢視繫結   問題 文件與檢視繫結後,在檢視中如何獲取文件指標?   新建MFC多文件工程(命名為Test),自動生成了一個C

JavaScript深入之 執行上下文作用域

作用域 作用域是指程式原始碼中定義變數的區域。 作用域規定了如何查詢變數,也就是確定當前執行程式碼對變數的訪問許可權。下面我們來看看作用域的兩種解析方式。 作用域兩種解析方式: 靜態作用域:js使用

OpenStack節點安裝基本環境

本文開始,記錄一下自己安裝OpenStack各服務元件的過程,將其中碰到的一些問題也與大家分享一下,希望能對各位有些許的幫助! 在此之前一直都是使用的DevStack開發環境在除錯程式碼,這段

keras執行例項regression迴歸

小編在自學機器學習過程中,參考莫煩大佬的python教程進行了keras的例項執行,在此記錄一下,以免忘記。 keras在Linux的安裝很簡單,直接   pip install keras   一行命令就可以啦,結果如下: 因為呢我已經安裝過了,所以會提示alrea

Pytest測試框架pytest安裝及用例執行

PyTest是基於Python的開源測試框架,語法簡單易用,有大量的外掛,功能非常多。自動檢測測試用例,支援引數化,跳過特定用例,失敗重試等功能。 # 安裝 ```python pip install -U pytest  # 安裝 pytest --version # 檢視版本 pytest

《機器學習》學習筆記線性回歸邏輯回歸

ros XA andrew ID learn 給定 編程練習 size func 《機器學習》學習筆記(一):線性回歸、邏輯回歸 本筆記主要記錄學習《機器學習》的總結體會。如有理解不到位的地方,歡迎大家指出,我會努力改正。 在學習《機器學習》時,我主要是

javaweb學習筆記web入門簡介tomcat

目錄 1.web入門 2.tomcat 2.1 Tomcat的安裝與使用 2.2 Tomcat的目錄結構 2.3 Web應用的目錄結構 1.web入門 B/S (Broswer -Server 瀏覽器端- 伺服器端)架構,其典型應用就是各種網站。它的特點是第一,不

Java學習第一章 計算機程式和Java概述

第一章 計算機、程式和Java概述   (1)匯流排--》    儲存裝置、記憶體、CPU、通訊裝置、輸入裝置、輸出裝置; (2)語言: 機器語言: 二進位制形式

Java常用的八種排序演算法與程式碼實現氣泡排序法插入排序法選擇排序法

這三種排序演算法適合小規模資料排序 ---   共同點:基於比較,時間複雜度均為O(n2),空間複雜度均為O(1)(原地排序演算法)   不同點:插入排序和氣泡排序是穩定的排序演算法,選擇排序不是 ---   穩定排序演算法:可以保持數值相等的兩個物件,在排序之

Jpeglib開發筆記JpegLib庫介紹編譯Demo和工程模板

原博主部落格地址:https://blog.csdn.net/qq21497936 本文章部落格地址:https://blog.csdn.net/qq21497936/article/details/86155043     Jpeglib開發筆記(一):JpegLi

SpringCloud註冊中心Eurekafeign簡單微服務搭建

1.Eureka簡介 Eureka是Netflix開源的一款提供服務註冊和發現的產品,它提供了完整的Service Registry和Service Discovery實現。也是springcloud體系中最重要最核心的元件之一。 Eureka是一個服務註冊和發現模組,採

doxygen註釋語法JavaDoc註釋風格檔案頭和類註釋

1、JavaDoc註釋風格 註釋風格有多種,本文采用JavaDoc註釋風格 Java風格如下,註釋第一行為/**,然後中間每一行註釋以*號開始,且為了方便閱讀,一般*後空一字元,最後一行以*/結束,*與上一行*對齊。 /** * * * */ 2、簡要註釋和詳細註釋

XV6操作系統代碼閱讀心得啟動加載中斷與系統調用

tel 包括 sched main函數 結構 依次 bss comm 啟動 XV6操作系統是MIT 6.828課程中使用的教學操作系統,是在現代硬件上對Unix V6系統的重寫。XV6總共只有一萬多行,非常適合初學者用於學習和實踐操作系統相關知識。 MIT 6.828的課程

libzip開發筆記libzip庫介紹編譯和工程模板

  前言   Qt使用一些壓縮解壓功能,選擇libzip庫,libzip庫比較原始,也是很多其他庫的基礎支撐庫。   libzip   libzip是一個C庫,用於讀取,建立和修改zip檔案。可以從資料緩衝區,檔案或直接從其他zip歸檔檔案直接複製的壓縮資料中新增檔案。在不關

java執行系列ThreadRunnableCallable實現執行區別

實現多執行緒 java實現多執行緒的方法有三種,分別是繼承thread類,實現runnable介面,實現callable介面(call方法有返回值) /** * 繼承Thread */ public class MyThread extends Thread{ int a = 0;