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