1. 程式人生 > 其它 >Unity3D -Thread多執行緒,Queue佇列,lock關鍵字

Unity3D -Thread多執行緒,Queue佇列,lock關鍵字

技術標籤:C#Unity3D

例一:

1.Thread 多執行緒

Unity裡一般用於Socket連線,開一條執行緒接訊息。

2.Queue佇列

物件的先進先出集合,可以規定特定型別的佇列集合,也可以什麼型別都存入佇列。

Queue aaa = new Queue(); Queue<int> aaa = new Queue<int>(); 都是可以的。

3.lock 關鍵字

主要用於處理併發問題、鎖定獨佔物件。鎖定的必須是引用型別!

先寫一個執行緒類,不用繼承MonoBehaviour。

public class XianCheng
{
 
    public Thread ThreadOne;
    public Thread ThreadTwo;
 
    public Queue<int> queue = new Queue<int>(); //先進先出佇列
 
    public void StartXianCheng()
    {
 
        //執行緒1
        ThreadOne = new Thread(Count);       //執行緒開始方法
        ThreadOne.IsBackground = true;       //後臺執行緒會隨著主執行緒結束退出
      //ThreadOne.Name = "Xiancheng1";       //執行緒名字
        ThreadOne.Start();                   //開始執行緒
 
        //執行緒2
        ThreadTwo = new Thread(Count);
        ThreadTwo.Start();
 
    }
 
 
    public void Count()
    {
                                              //這裡可以註釋掉lock來測試
            lock (queue)                      //鎖定佇列,必須等待一條執行緒訪問完成後,別的執行緒才能使用
            {
                queue.Enqueue(1);             //入隊
             // queue.Dequeue();              //出隊,返回佇列開始處的物件,並且刪除它!
 
 
                Thread.Sleep(1000);           //執行緒休眠毫秒數
             // ThreadOne.Suspend();          //暫停執行緒
             // ThreadOne.Resume();           //繼續執行緒
 
            }
     }
 
}

再寫一個類,很簡單。

public class NewBehaviourScript : MonoBehaviour {
 
    XianCheng xiancheng;
 
	void Start () {
        xiancheng = new XianCheng();
        xiancheng.StartXianCheng();
	}
	
 
	void Update () {
         Debug.Log(xiancheng.queue.Count);  //lock的話,列印先1後2,不lock直接2,因為兩個執行緒同時使用了佇列。
	}
 
    
    void OnApplicationQuit()
    {
       xiancheng.ThreadTwo.Abort();               //終止執行緒1
       xiancheng.ThreadOne.Abort();               //終止執行緒2
    }
}

例二:

using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class QueueExample : MonoBehaviour
{
    public Queue queue;
    public Text queueCount;
    public Text queueContent;
    public Text queuePeek;

    void Start()
    {
        queue = new Queue();
    }

    void Update()
    {
        if (queue.Count > 0)
        {
            queuePeek.text = "queuePeek : " + queue.Peek().ToString();
        }
        else
        {
            queuePeek.text = "queuePeek : ";
        }

        //增加元素
        if (Input.GetKeyDown(KeyCode.A))
        {
            InsetTime();
            showQueue();
        }

        //減去元素
        if (Input.GetKeyDown(KeyCode.D))
        {
            if (queue.Count > 0)
            {
                Debug.Log(queue.Dequeue());
                showQueue();
            }
        }

        //清除佇列所有元素
        if (Input.GetKeyDown(KeyCode.C))
        {
            queue.Clear();
            showQueue();
        }

        queueCount.text = "queueCount : " + queue.Count.ToString();
    }

    void InsetTime()
    {
        queue.Enqueue(Time.time);
    }

    void showQueue()
    {
        queueContent.text = "queueContent : ";
        foreach (float value in queue)
        {
            queueContent.text += value.ToString() + " | ";
        }
    }
}

例三:

//用平均值的方法平滑陀螺儀曲線,實現思想簡單描述如下
Queue<Quaternion> averageList;
averageList.Enqueue (Input.gyro.attitude);
if (averageList.Count > 240)
averageList.Dequeue ();
foreach (Quaternion singleRotation in averageList)
{
//分離,重組Quaternion,獲得平均值averageRotation
}
//通過插值貼回給攝像頭
transform.localRotation = Quaternion.Slerp(transform.localRotation, averageRotation, Time.deltaTime* 4f);

Queue的基本功能有插入、提取和檢查操作。可以用來如排隊,計時等線性相關的問題。通過插入,提取,檢查,清除等操作了解queue的執行,

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
 
public class QueueExample : MonoBehaviour
{
    public Queue queue;
    public Text queueCount;
    public Text queueContent;
    public Text queuePeek;
 
    void Start()
    {
        queue = new Queue();
    }
 
    void Update()
    {
        if (queue.Count > 0)
        {
            queuePeek.text = "queuePeek : " + queue.Peek().ToString();
        }
        else
        {
            queuePeek.text = "queuePeek : ";
        }
 
        //增加元素
        if (Input.GetKeyDown(KeyCode.A))
        {
            InsetTime();
            showQueue();
        }
 
        //減去元素
        if (Input.GetKeyDown(KeyCode.D))
        {
            if (queue.Count > 0)
            {
                Debug.Log(queue.Dequeue());
                showQueue();
            }
        }
 
        //清除佇列所有元素
        if (Input.GetKeyDown(KeyCode.C))
        {
            queue.Clear();
            showQueue();
        }
 
        queueCount.text = "queueCount : " + queue.Count.ToString();
    }
 
    void InsetTime()
    {
        queue.Enqueue(Time.time);
    }
 
    void showQueue()
    {
        queueContent.text = "queueContent : ";
        foreach (float value in queue)
        {
            queueContent.text += value.ToString() + " | ";
        }
    }
}

例四:訊息廣播中心

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using System;

public class GameEvent{ }

public class EventQueueSystem : MonoSingleton<EventQueueSystem>
{
    public delegate void EventDelegate<T>(T e) where T : GameEvent;

    private delegate void InternalEventDelegate(GameEvent e);

    private Dictionary<Type, InternalEventDelegate> delegates = new Dictionary<Type, InternalEventDelegate>();
    private Dictionary<Delegate, InternalEventDelegate> delegateLookup = new Dictionary<Delegate, InternalEventDelegate>();
    private Dictionary<InternalEventDelegate, Delegate> delegateLookOnce = new Dictionary<InternalEventDelegate, Delegate>();

    private Queue eventQueue = new Queue();

    public bool bLimitQueueProcessing = false;
    public float limitQueueTime = 0.1f;

    //註冊偵聽事件(持續)
    public static void AddListener<T>(EventDelegate<T> del) where T : GameEvent
    {
        Instance.AddDelegate(del);
    }

    //註冊偵聽事件(一次)
    public static void AddListenerOnce<T>(EventDelegate<T> del) where T : GameEvent
    {
        var result = Instance.AddDelegate(del);
        if (result != null)
            Instance.delegateLookOnce[result] = del;
    }

    //判定偵聽事件是否存在
    public static bool HasListener<T>(EventDelegate<T> del) where T : GameEvent
    {
        return Instance.delegateLookup.ContainsKey(del);
    }

    //移除偵聽事件
    public static void RemoveListener<T>(EventDelegate<T> del) where T : GameEvent
    {
        if (Instance == null)
            return;
        if (Instance.delegateLookup.TryGetValue(del, out InternalEventDelegate eventDelegate))
        {
            if (Instance.delegates.TryGetValue(typeof(T), out InternalEventDelegate temp))
            {
                temp -= eventDelegate;
                if (temp == null)
                    Instance.delegates.Remove(typeof(T));
                else
                    Instance.delegates[typeof(T)] = temp;
            }
            Instance.delegateLookup.Remove(del);
        }
    }

    public static void RemoveAll()
    {
        if (Instance != null)
        {
            Instance.delegates.Clear();
            Instance.delegateLookup.Clear();
            Instance.delegateLookOnce.Clear();
        }
    }

    private InternalEventDelegate AddDelegate<T>(EventDelegate<T> del) where T : GameEvent
    {
        if (delegateLookup.ContainsKey(del))
            return null;
        void eventDelegate(GameEvent e) => del((T)e);
        delegateLookup[del] = eventDelegate;

        if (delegates.TryGetValue(typeof(T), out InternalEventDelegate temp))
            delegates[typeof(T)] = temp += eventDelegate;
        else
            delegates[typeof(T)] = eventDelegate;
        return eventDelegate;
    }

    //單個事件觸發
    private static void TriggerEvent(GameEvent e)
    {
        var type = e.GetType();
        if(Instance.delegates.TryGetValue(type,out InternalEventDelegate eventDelegate))
        {
            eventDelegate.Invoke(e);
            //移除單一偵聽
            foreach(InternalEventDelegate item in Instance.delegates[type].GetInvocationList())
            {
                if (Instance.delegateLookOnce.TryGetValue(item,out Delegate temp))
                {
                    Instance.delegates[type] -= item;
                    if (Instance.delegates[type] == null)
                        Instance.delegates.Remove(type);
                    Instance.delegateLookup.Remove(temp);
                    Instance.delegateLookOnce.Remove(item);
                }
            }
        }
    }

    //外部呼叫的推入事件佇列介面
    public static void QueueEvent(GameEvent e)
    {
        if (!Instance.delegates.ContainsKey(e.GetType()))
            return;
        Instance.eventQueue.Enqueue(e);
    }

    //事件佇列觸發處理
    void Update()
    {
        float timer = 0.0f;
        while (eventQueue.Count > 0)
        {
            if (bLimitQueueProcessing)
                if (timer > limitQueueTime)
                    return;
            var e = eventQueue.Dequeue() as GameEvent;
            TriggerEvent(e);
            if (bLimitQueueProcessing)
                timer += Time.deltaTime;
        }
    }

    private void OnApplicationQuit()
    {
        RemoveAll();
        eventQueue.Clear();
    }
}

https://blog.csdn.net/u012322710/article/details/52885756

https://www.cnblogs.com/koshio0219/p/11209191.html