Unity3D -Thread多线程,Queue队列,lock关键字

Unity3D -Thread多线程,Queue队列,lock关键字

例一:

1.Thread 多线程

Unity里一般用于Socket连接,开一条线程接消息。

2.Queue队列

对象的先进先出集合,可以规定特定类型的队列集合,也可以什么类型都存入队列。

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

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();
    }
}