CS5L7-1——线程和线程池

本章代码关键字

1
2
3
4
5
6
7
ThreadPool                            //线程池类(静态类)
ThreadPool.GetAvailableThreads() //获取可用的工作线程数和I/O线程数(应用程序内可开的最大线程数量)
ThreadPool.GetMaxThreads() //获取线程池中工作线程的最大数目和I/O线程的最大数目(该应用程序最多可用的线程池的线程数量)
ThreadPool.SetMaxThreads() //设置线程池中可以同时处于活动状态的工作线程的最大数目和I/O线程的最大数目
ThreadPool.GetMinThreads() //获取线程池中工作线程的最小数目和I/O线程的最小数目(该应用程序线程池内默认存在的线程数量)
ThreadPool.SetMinThreads() //设置工作线程的最小数目和I/O线程的最小数目
ThreadPool.QueueUserWorkItem() //将方法排入队列以便执行,当线程池中线程变得可用时执行

回顾知识点——线程

关于Unity的多线程,具体看这里 ——> Unity是否支持多线程

  1. Unity支持多线程
  2. Unity中开启的多线程不能使用主线程中的对象
  3. Unity中开启多线程后一定记住关闭(否则会与编辑器共生,直到关闭编辑器)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Thread t;

void Start()
{
t = new Thread(() =>
{
while (true)
{
print("123");
Thread.Sleep(1000);
//print(this.transform.position); 该操作Unity并不允许!
}
});
t.Start();
print("主线程执行");
}

private void OnDestroy()
{
t.Abort(); //目的是在运行结束后停止多线程,否则多线程会与编辑器共生
}

线程池

线程池相当于就是一个专门装线程的缓存池(Unity小框架套课中有对缓存池的详细讲解)

  • 优点:节省开销,减少线程的创建,进而有效减少GC触发
  • 缺点:不能控制线程池中线程的执行顺序,也不能获取线程池内线程取消/异常/完成的通知

命名空间:System.Threading
类名:ThreadPool​(线程池)

在多线程的应用程序开发中,频繁的创建删除线程会带来性能消耗,产生内存垃圾
为了避免这种开销 C# 推出了线程池 ThreadPool​ 类

ThreadPool​ 中有若干数量的线程,如果有任务需要处理时,会从线程池中获取一个空闲的线程来执行任务
任务执行完毕后线程不会销毁,而是被线程池回收以供后续任务使用
当线程池中所有的线程都在忙碌时,又有新任务要处理时,线程池才会新建一个线程来处理该任务,
如果线程数量达到设置的最大值,任务会排队,等待其他任务释放线程后再执行
线程池能减少线程的创建,节省开销,可以减少GC垃圾回收的触发

ThreadPool​ 是一个静态类,里面提供了很多静态成员,其中相对重要的方法有

  1. 获取可用的工作线程数和I/O线程数(应用程序内可开的最大线程数量)

    1
    2
    3
    4
    5
    int workerThreadsNum;
    int completionPortThreads;
    ThreadPool.GetAvailableThreads(out workerThreadsNum, out completionPortThreads);
    print(workerThreadsNum);
    print(completionPortThreads);
  2. 获取线程池中工作线程的最大数目和I/O线程的最大数目(该应用程序最多可用的线程池的线程数量)

    1
    2
    3
    ThreadPool.GetMaxThreads(out workerThreadsNum, out completionPortThreads);
    print(workerThreadsNum);
    print(completionPortThreads);
  3. 设置线程池中可以同时处于活动状态的工作线程的最大数目和I/O线程的最大数目
    大于设置的次数的添加线程请求将保持排队状态,直到线程池线程变为可用,更改成功返回true,失败返回false

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    if (ThreadPool.SetMaxThreads(20, 20))
    {
    print("更改成功!");
    ThreadPool.GetMaxThreads(out workerThreadsNum, out completionPortThreads);
    print(workerThreadsNum);
    print(completionPortThreads);
    }
    else
    {
    print("更改失败!");
    }
  4. 获取线程池中工作线程的最小数目和I/O线程的最小数目(该应用程序线程池内默认存在的线程数量)

    1
    2
    3
    ThreadPool.GetMinThreads(out workerThreadsNum, out completionPortThreads);
    print(workerThreadsNum);
    print(completionPortThreads);
  5. 设置 工作线程的最小数目和I/O线程的最小数目
    更改成功返回 true​,失败返回 false

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    if (ThreadPool.SetMinThreads(4, 4))
    {
    print("更改成功!");
    ThreadPool.GetMinThreads(out workerThreadsNum, out completionPortThreads);
    print(workerThreadsNum);
    print(completionPortThreads);
    }
    else
    {
    print("更改失败!");
    }
  6. 将方法排入队列以便执行,当线程池中线程变得可用时执行
    第一个参数就是多线程要执行的方法,方法需要一个 object​ 类型参数
    第二个参数就是第一个参数的函数的传入的参数

    1
    2
    3
    4
    5
    6
    ThreadPool.QueueUserWorkItem((obj) =>
    {
    print(obj);
    print("开启了一个线程");
    }, "123456789");
    print("主线程执行");

    要注意!我们不能控制线程执行的顺序!

    1
    2
    3
    4
    5
    6
    7
    for (int i = 0; i < 10; i++)
    {
    ThreadPool.QueueUserWorkItem((obj) =>
    {
    print("第" + obj + "个任务");
    }, i);
    }