[多線程] 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
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...