[多線程] Thread

来源:https://www.cnblogs.com/ASsss/archive/2019/02/26/10438885.html
-Advertisement-
Play Games

多線程 概述 單任務處理:一個任務完成後才能進行下一個任務。 多任務處理:CPU分時操作,每個任務看似同時運行。 進程 應用程式的一個運行實例,包含程式所需資源的記憶體區域,是操作系統進行資源分配的單元,進程隔離了正在執行的不同程式。(打開某一個軟體,分配CPU,隔離其他軟體) 優點:進程間相互獨立, ...


 

多線程

概述

單任務處理:一個任務完成後才能進行下一個任務。

多任務處理:CPU分時操作,每個任務看似同時運行。

進程

應用程式的一個運行實例,包含程式所需資源的記憶體區域,是操作系統進行資源分配的單元,進程隔離了正在執行的不同程式。(打開某一個軟體,分配CPU,隔離其他軟體)

優點:進程間相互獨立,互不影響。

線程

進程中的一個執行單元(進程是程式邊界,要靠線程執行程式,線程指向方法,執行完畢釋放線程),是CPU分配時間片的單位,一個進程可以包含多個線程,且相互獨立,共用當前進程所有資源。

優點:

  1. 併發執行,合理使用CPU資源
  2. 相同程式的線程共用堆記憶體。

缺點:

  1. 頻繁創建/銷毀線程增加性能開銷。
  2. 訪問共用資源可能造成衝突。
  3. 輔助線程不能訪問Unity API。

註意事項

  1. Unity的API不能在輔助線程運行。
  2. Unity定義的基本結構(int,Vector3,Quaternion等)可以在輔助線程計算。
  3. Unity定義的基本類型的函數可以在分線程運行。

多線程

在單核系統的一個單位時間內,CPU只能運行單個線程,運行順序取決於線程的優先順序。如果在單位時間內線程未能完成執行,系統就會把線程的狀態信息保存到線程的本地存儲器(TLS) 中,以便下次執行時恢復執行。因為切換頻密,所以多線程可被視作同時運行,而實際只是一個假象。

在多核系統的一個單位時間內,進程或線程可以在不同的CPU中運行,使得真正的並行處理。

適用性

耗時的任務,通過多線程可以並行處理。

一個程式完成多個任務,通過多個線程使用多核CPU來處理可以提升性能

線程實現

命名空間:System.Threading;

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;

public class ThreadDemo1 : MonoBehaviour
{
    private Thread thread;
    private void Start01()
    {
        //Func1();//同步調用  一次性完成0 1 2 3 4 ....

        //線程調用
        //thread = new Thread(Fun1);
        //thread.Start();
        //睡眠一秒 期間沒有CPU調度 0 睡眠一秒,依次迴圈 1 2 3 4... 

        //thread = new Thread(Fun2);
        //thread.Start(5);
        //方法重載  參數object類型

        thread = new Thread(Fun4);
        thread.Start();

        //ThreadPool.QueueUserWorkItem(Fun3,null);
        //線程池開闢的線程無法設置前後臺/優先順序等
        //通過線程池開闢線程 不能Start啟用
    }
    //thread.Start()  //無參
    private void Fun1()
    {
        for (int i = 0; i < 30; i++)
        {
            signal.WaitOne(3000);
            //整數  代表最長的等待時間
            Thread.Sleep(1000);
            print(i);
        }
    }
    ////thread.Start(5)  //有參
    private void Fun2(object o)
    {
        int count = (int)o;
        for (int i = 0; i < count; i++)
        {
            Thread.Sleep(1000);
            print(i);
        }
    }
    /// <summary>
    /// 對象池
    /// </summary>
    private void Fun3(object o)
    {
        //int[] arr = (int[])o;
        //int count = (int)o;
        for (int i = 0; i < 5; i++)
        {
            Thread.Sleep(1000);//模擬此時操作一分鐘
            print(i);//主線程 卡   指的就是生命周期

        }
    }

    /// <summary>
    /// 死迴圈 怎麼辦
    /// </summary>
    private void Fun4()
    {
        int n = 0;
        while (true)
        {
            Thread.Sleep(1000);
            print(++n);
        }
    }
    /// <summary>
    /// 退出線程
    /// </summary>
    private void OnApplicationQuit()
    {
        //thread.Abort();
        //結束線程
        //主線程卡頓的情況  可以開闢新的線程
    }
    /// <summary>
    /// 信號燈
    /// </summary>
    private ManualResetEvent signal;

    private void Start()
    {
        //信號燈 綠燈行  紅燈停
        signal = new ManualResetEvent(true);
        //true表示綠燈 false 表示紅燈
        thread = new Thread(Fun1);
        thread.Start();
    }
    private void OnGUI()
    {
        if (GUILayout.Button("線程暫停"))
        {
            signal.Reset();
        }
        if (GUILayout.Button("線程繼續"))
        {
            signal.Set();
        }
    }
}
View Code

Thread 

  1. 創建線程: 創建Thread一個對象,分配一個線程作方法 

             Thread thread = new Thread(工方法);

  1. 線程Start方法。

             thread.Start();

  1. 終止線程:工作方法自然退出、線程終止。

             thread. Abort ();

ThreadPool

在頻繁創建和銷毀線程時使用線程池技術,可以有效減少時間以及系統資源的開銷

ThreadPool.QueueUserWorkItem(工作方法);

 

/後臺線程

 

前臺線程:程式必須等待所有前臺線程結束後才能退出。(只要有一個前臺線程未退出,進程就不會終止!即說的就是程式不會關閉!)[Thread創建的線程預設前臺線程]

 

後臺線程:程式不考慮後臺線程,後臺線程隨程式退出而結束。[ThreadPool創建的線程預設後臺線程]

 

備註Unity程式退出後,前臺線程也隨即關閉。

 

新建的子線程可以是前臺線程或者後臺線程,前臺線程必須全部執行完,即使主線程關閉掉,這時進程仍然存活。

 

線程狀態

啟動狀態 Unstarted創建線程對象

運行狀態Running執行綁定的方法。

等待睡眠阻塞狀態 WaitSleepJoin:暫時停止執行資源交給其他線程使用

終止狀態 Stopped線程銷毀

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.UI;
using System.Threading;


public class ThreadDemo : MonoBehaviour
{
    private int second = 60;
    private Text text;
    private void Start()
    {
        text = GetComponent<Text>();
        Thread thread = new Thread(Timer);
        thread.Start();
    }
    private void Update()
    {
        if (action!=null)
        {
            action();
            action = null;
        }
    }
    private void Timer()
    {
        while (second>0)
        {
            Thread.Sleep(1000);//睡一會  期間沒有CPU的調度

            action = () =>
            {
                second--;
                text.text = string.Format("{0:d2}:{1:d2}", second / 60, second % 60);
            };
        }   
    }
    private Action action;
}

線程同步

需要同步的原因: 

多個線程同一時刻訪問共用資源(線程共用實例變數,靜態變數)由於每個線程都不知道其他線程的操作結果將產生不可預知的數據損壞。 

 

步:

線程之間相互等待排隊執行

 

何同步:

需要同步的代碼用關鍵字lock定,鎖定後該代碼對於線程來講是獨占使用的。當其他線程試圖進入被鎖定的臨界區時只能等待解鎖後才可訪問。鎖定代碼時是排訪問的,所以叫線程同步。 

 

Lock鎖原理:

對象在堆中的分配:實例成員、同步塊索引 (預設索引-1)類型指針(指向類型對象)。      

對象上鎖後,同步索引塊會指向同步塊數組中的一個對象。

當其他對象執行lock的時候會等待該對象同步索引設置為-1

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;

public class Bank
{
    public static int Money = 1;
    public static object o = new object();
    //必須使用引用類型
    //優先使用object
    public static void Get(int val)
    {
        lock (o)//-1   0  只有是-1的時候  鎖打開  否則鎖關閉
        {          //同步塊索引 類型對象指針
                   //共用讀  獨占寫
                   //枷鎖(對象)  流程
            if (Money >= val)
            {
                //線程衝突 0  -1   -2  如何解決???加鎖
                Thread.Sleep(1000);
                Money -= val;
                Debug.Log("取錢成功!餘額:" + Money);
            }
            else
            {
                Debug.Log("取錢失敗!餘額:" + Money);
            }
            //線程離開代碼塊  索引塊  設置為-1
        }
    }
}


public class ThreadDemo2 : MonoBehaviour
{
    private void Start()
    {
        //Bank.Get(1);  //同步調用  排隊
        ThreadPool.QueueUserWorkItem(o =>
        {
            Bank.Get(1);
        });
        ////線程調用(多線程)  不排隊
    }
}

 


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

-Advertisement-
Play Games
更多相關文章
  • 基本代碼結構 url.py: views.py: 說明: has_permission方法的返回值是布爾類型,True表示許可權通過,False表示許可權拒絕 上面的基本結構是做局部的類的許可權判斷方式,全局許可權判斷後文介紹。 permission_classes屬性變數同樣也是一個列表,列表元素是許可權判 ...
  • 題意 "題目鏈接" Sol 這題想還是不難想的,就是寫起來很麻煩,然後去看了一下loj的最短代碼表示只能Orz 首先不難發現一條性質:能夠選擇的區間一定是不斷收縮的,而且新的可選區間一定是舊區間的某個位置劃分而來的。 比如$A_{i 1} = x$,此時小於$x$的最大數為$l_{i 1}$,大於$ ...
  • 本文從零開始介紹如何使用 Supervisor,一步一步的從安裝環境到編寫托管服務文件,設置執行文件、執行文件目錄、日誌輸出配置等細節,最終成功將 .NET Core 應用程式托管到了 Supervisor 中 ...
  • 前文說道了Action的激活,這裡有個關鍵的操作就是Action參數的映射與模型綁定,這裡即涉及到簡單的string、int等類型,也包含Json等複雜類型,本文詳細分享一下這一過程。(ASP.NET Core 系列目錄) 一、概述 當客戶端發出一個請求的時候,參數可能存在於URL中也可能是在請求的 ...
  • 使用過代碼生成器的開發人員應該知道,通過代碼生成器生成項目的代碼,可以大大的減少重覆編碼的時間,提供項目開發的效率,將自己從繁雜重覆的代碼中解放出來。現在網路上也有很多的開源的代碼生成器或者使用比較廣泛的代碼生成器,如動軟代碼生成器相信不少開發人員使用過。有時候線上的代碼生成器生成的代碼未必百分之百 ...
  • 首先 在 EntityFrameworkCore中安裝 Microsoft.Extensions.Logging.Console 按照官方文檔 使用UseLoggerFactory 方法 (地址:https://docs.microsoft.com/zh-cn/ef/core/miscellaneo ...
  • <img src="../../img/20190224185111.png" alt="" id="zhaopian"/> //定義變數 var img = ""; //圖片點擊 $("#zhaopian").click(function () { //賦值獲取圖片路徑 img = $(this) ...
  • 一、迭代器(Iterator)通過持有迭代狀態可以獲取當前迭代元素並且識別下一個需要迭代的元素,從而可以遍歷集合中每一個元素而不用瞭解集合的具體實現方式; 實現迭代器功能的方法被稱為迭代器方法,迭代器方法的返回值類型可以是以下4種介面類型中任意一種:位於命名空間System.Collections中 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...