java線程的6種狀態以及相互轉換

来源:http://www.cnblogs.com/wl2014/archive/2017/11/01/7765701.html
-Advertisement-
Play Games

線程如何創建 創建線程有三種方式:繼承Thread類;無返回值的Runnable;有返回值的Callable 示例如下 執行結果 線程相關的基礎方法 wait:獲取鎖對象monitor的線程執行wait方法,將會釋放對monitor的控制權,其他線程可以獲取到鎖對象的monitor,執行notify ...


線程如何創建

創建線程有三種方式:繼承Thread類;無返回值的Runnable;有返回值的Callable

示例如下

package com.rcl.platform.demo;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class CreateThread {

    public static class TestThread extends Thread {
        @Override
        public void run() {
            System.out.println("--繼承thread--");
        }
    }

    public static class TestRunnable implements Runnable {

        @Override
        public void run() {
            System.out.println("--runnable沒有返回值--");
        }

    }

    public static class TestCallable implements Callable<String> {

        @Override
        public String call() throws Exception {
            System.out.println("--callable有返回值--");
            return "test-callable";
        }

    }
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        Thread thread = new Thread(new TestThread());
        thread.start();

        thread = new Thread(new TestRunnable());
        thread.start();

        FutureTask<String> ft = new FutureTask<>(new TestCallable());  
        thread = new Thread(ft);
        thread.start();

        System.out.println(ft.get());


    }
}

執行結果

--繼承thread--
--runnable沒有返回值--
--callable有返回值--
test-callable

線程相關的基礎方法

wait:獲取鎖對象monitor的線程執行wait方法,將會釋放對monitor的控制權,其他線程可以獲取到鎖對象的monitor,執行notify喚醒wait線程

notify/notifyall:獲取到monitor,喚醒曾經獲取到monitor執行wait正在處於等待的線程(線程狀態為WAITING,TIMED_WAITING)

sleep:線程休眠

yield:yield方法的作用是暫停當前線程,以便其他線程有機會執行,不過不能指定暫停的時間,並且也不能保證當前線程馬上停止。yield方法只是將Running狀態轉變為Runnable狀態(不能完全保證,最好少用)

join:join方法的作用是父線程等待子線程執行完成後再執行,換句話說就是將非同步執行的線程合併為同步的線程,如:如果在mian線程執行的過程中執行t1.join方法,那麼將轉而執行t1線程,t1線程執行完畢後執行mian線程

package com.rcl.platform.demo;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

public class JoinTest {

    public static class TestThread extends Thread {
        @Override
        public void run() {
            for(int i=0; i<10; i++){
                System.out.println("第" + i + "次執行");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) throws InterruptedException, ExecutionException {

        TestThread thread = new TestThread();
        thread.start();

        thread.join();
        System.out.println("等待thread執行完畢後main線程結束");
    }
}

執行結果

第0次執行
第1次執行
第2次執行
第3次執行
第4次執行
第5次執行
第6次執行
第7次執行
第8次執行
第9次執行
等待thread執行完畢後main線程結束

interrupt:他的作用是“停止”當前線程的運行,為什麼加上一個引號,它只在特殊情況下有用,像線程調用了wait,sleep,join等可中斷的阻塞方法 後,調用interrupt就會拋出InterruptedException異常。其實它稱為協作停止。調用了這個方法後線程除了特殊情況外別的時候並不會停止,它發送一個停止請求,並且由線程記錄下來(實際上就是有一個為bool的變數,當為true時就表示有停止線程運行請求)。所以說線程真正的停止需要我們自己去檢查是否有停止線程的請求,當有線程停止請求時停用當前線程。和他配套是使用的有

public static boolean interrupted()

public boolean isInterrupted()

package com.rcl.platform.demo;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

public class JoinTest {

    public static class TestThread extends Thread {
        @Override
        public void run() {
            for(int i=0; i<1000000000; i++){
                System.out.println("TestThread第" + i + "次執行");
                if(Thread.interrupted()){  
                    return;  
                }
        }
        }
    }

    public static class TestThreadSleep extends Thread {
        @Override
        public void run() {
            for(int i=0; i<10; i++){
                System.out.println("TestThreadSleep第" + i + "次執行");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if(Thread.interrupted()){  
                    return;  
                }
        }
        }
    }

    public static void main(String[] args) throws InterruptedException, ExecutionException {

        TestThread thread = new TestThread();
        thread.start();
        thread.interrupt();

        TestThreadSleep threadSleep = new TestThreadSleep();
        threadSleep.start();
        threadSleep.interrupt();
    }
}

執行結果

TestThread第0次執行
TestThreadSleep第0次執行
java.lang.InterruptedException: sleep interruptedTestThreadSleep第1次執行

    at java.lang.Thread.sleep(Native Method)
    at java.lang.Thread.sleep(Thread.java:340)
    at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
    at com.rcl.platform.demo.JoinTest$TestThreadSleep.run(JoinTest.java:27)
TestThreadSleep第2次執行
TestThreadSleep第3次執行
TestThreadSleep第4次執行
TestThreadSleep第5次執行
TestThreadSleep第6次執行
TestThreadSleep第7次執行
TestThreadSleep第8次執行
TestThreadSleep第9次執行

線程狀態

1、java線程有6中狀態,分別為NEW,RUNNABLE,BLOCKED,WAITING,TIMED_WAITING,TERMINATED詳解java.lang.Thread$State枚舉類

2、線程初始化為NEW狀態,該狀態表示還未調用start方法

3、執行線程調用start方法,線程狀態轉換為RUNNABLE(包括競爭到CPU時間真正意義的執行和沒有競爭到CPU時間等待下一個CPU時間的狀態)

4、BLOCKED狀態為鎖競爭,沒有競爭到鎖為BLOCKED,等待擁有鎖的線程釋放鎖,進入RUNNABLE狀態

5、WAITING狀態為競爭到鎖,執行wait方法,又釋放鎖,本線程進入WAITING,等待其他線程喚醒notify,notifyall,如果不喚醒,將一直處於WAITING狀態

6、TIMED_WAITING為執行sleep join或者有時限的等待

7、線程執行完畢,線程處於TERMINATED狀態

線程狀態變化

package com.rcl.platform.demo;

import java.util.concurrent.TimeUnit;

public class ThreadState {
    public static void main( String[] args ) throws InterruptedException {
        System.out.println("-------------NEW-------------");
        Thread thread = new Thread();
        System.out.println(thread.getState() + ":" + (thread.getState() == Thread.State.NEW));

        System.out.println("-------------分割線-------------");

        System.out.println("-------------RUNNABLE、TERMINATED-------------");
        thread = new Thread(new Runnable() {
            public void run() {
                System.out.println(Thread.currentThread().getState() + ":" + (Thread.currentThread().getState() == Thread.State.RUNNABLE));
            }
        });
        thread.start();

        TimeUnit.SECONDS.sleep(1);
        System.out.println(thread.getState() + ":" + (thread.getState() == Thread.State.TERMINATED));

        System.out.println("-------------分割線-------------");

        System.out.println("-------------RUNNABLE、TIMED_WAITING-------------");
        thread = new Thread(new Runnable() {
            public void run() {
                System.out.println(Thread.currentThread().getState() + ":" + (Thread.currentThread().getState() == Thread.State.RUNNABLE));
                System.out.println("sleep 進入 TIMED_WAITING");
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread.start();

        TimeUnit.SECONDS.sleep(1);
        System.out.println(thread.getState() );
        TimeUnit.SECONDS.sleep(2);

        System.out.println("-------------分割線-------------");


        System.out.println("-------------RUNNABLE、TIMED_WAITING-------------");
        final Thread mainThread = Thread.currentThread();
        thread = new Thread(new Runnable() {
            public void run() {
                System.out.println(Thread.currentThread().getState() + ":" + (Thread.currentThread().getState() == Thread.State.RUNNABLE));
                try {
                    System.out.println("join 進入 TIMED_WAITING");
                    System.out.println("mainThread: " + mainThread.getState());
                    TimeUnit.SECONDS.timedJoin(mainThread, 2);//先執行mainthread 
                    System.out.println("mainThread: " + mainThread.getState());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread.start();
        TimeUnit.SECONDS.sleep(1);
        System.out.println("testThread: " + thread.getState() );

        System.out.println("-------------分割線-------------");

        System.out.println("-------------RUNNABLE、WAITING-------------");
        Object lock = new Object();
        final Thread mainThread1 = Thread.currentThread();
        thread = new Thread(new Runnable() {
            public void run() {
                synchronized (lock) {
                    try {
                        System.out.println("wait 進入 WAITING");
                        lock.wait();
                        System.out.println("mainThread1: " + mainThread1.getState() );
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
            }
        });
        thread.start();
        TimeUnit.SECONDS.sleep(1);
        System.out.println("testThread: " + thread.getState() );
        synchronized (lock) {
            lock.notifyAll();
        }
        TimeUnit.SECONDS.sleep(1);

        System.out.println("-------------分割線-------------");
        Thread thread1 = new Thread(new Runnable() {
            public void run() {
                synchronized (lock) {
                    try {
                        TimeUnit.SECONDS.sleep(2);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
            }
        });
        thread1.start();
        Thread thread2 = new Thread(new Runnable() {
            public void run() {
                synchronized (lock) {

                }
            }
        });
        thread2.start();
        TimeUnit.SECONDS.sleep(1);
        System.out.println("thread2: " + thread2.getState() );
    }
}

執行結果

-------------NEW-------------
NEW:true
-------------分割線-------------
-------------RUNNABLE、TERMINATED-------------
RUNNABLE:true
TERMINATED:true
-------------分割線-------------
-------------RUNNABLE、TIMED_WAITING-------------
RUNNABLE:true
sleep 進入 TIMED_WAITING
TIMED_WAITING
-------------分割線-------------
-------------RUNNABLE、TIMED_WAITING-------------
RUNNABLE:true
join 進入 TIMED_WAITING
mainThread: TIMED_WAITING
testThread: TIMED_WAITING
-------------分割線-------------
-------------RUNNABLE、WAITING-------------
wait 進入 WAITING
mainThread: TIMED_WAITING
testThread: WAITING
mainThread1: TIMED_WAITING
-------------分割線-------------
thread2: BLOCKED

歡迎加入學習交流群569772982,大家一起學習交流。

 

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 之前 ,有想做一個文件管理頁面。 參考了 許多資料,終於完成了一個基於Asp.net MVC 的文件管理Demo.界面如下。 一,實現功能及相關技術 文件管理Demo基於Asp.NET MVC ,主要實現了 文件列表瀏覽,文件夾創建與刪除,文件夾以及文件重命名,文件與文件夾的複製、剪切、壓縮,文件與 ...
  • .net core已經發佈了2.0版本,相對於1.0的有了很大的完善,最近準備在項目中嘗試使用asp.net core,所以就進行了一些簡單的研究。 初識asp.net core分為以下幾個部分: 1、.net core SDK以及vs2017下載安裝 2、創建asp.net core項目 3、初識 ...
  • 1:做過圖像顯示的都知道,我們的圖片大部分都是壓縮過的,大部分為JPEG PNG BMP其中BMP格式是點陣形式,當圖片翻譯到記憶體之後無論壓沒壓縮過都會變成BMP格式放進記憶體,在這個過程中,圖片數據會幾倍的增大,就比如JPEG,一張1M大小的JPEG格式的圖片,翻譯到記憶體可能就會變成7倍左右,也就是 ...
  • C# 語言是在2000發佈的,至今已正式發佈了7個版本,每個版本都包含了許多令人興奮的新特性和功能更新。同時,C# 每個版本的發佈都與同時期的 Visual Studio 以及 .NET 運行時版本高度耦合,這也有助於開發者更好的學習掌握 C#,並將其與 Visual Studio 以及 .NET ... ...
  • 原文:https://www.stevejgordon.co.uk/asp-net-core-anatomy-part-3-addmvc 發佈於:2017年4月環境:ASP.NET Core 1.1 本系列前面兩篇文章介紹了ASP.NET Core中IServiceCollection兩個主要擴展方 ...
  • 1 環境搭建 1.1 Python安裝 1.2 MySQL環境搭建 1.3安裝MySQLdb 2 具體實現 2.1 登陸界面 2.2 註冊界面 2.3 具體實現部分代碼 1 環境搭建 1.1 Python安裝 本文具體實現部分Python環境:Python2.7.14,64位版本 具體安裝步驟見:P ...
  • 要求: 程式流程圖: 程式Readme: MiniFTP主要是由三部分組成:伺服器端、客戶端、管理端。本文主要就是介紹以上三部分內容。 系統初始配置 管理員賬號 用戶名:admin 密碼:password 用戶賬號: 用戶名:zhangsan 密碼:123 伺服器地址: IP:127.0.0.1 P ...
  • RabbitMQ依賴erlang,所以先安裝erlang,然後再安裝RabbitMQ; erlang,下載地址:http://www.erlang.org/download 先安裝erlang,雙擊erlang的安裝文件即可,然後配置環境變數: ERLANG_HOME=D:\Program File ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...