唤醒 ThreadPool 中现有线程的问题

The problem of waking up existing threads in the ThreadPool

提问人:SP222 提问时间:11/11/2023 更新时间:11/11/2023 访问量:52

问:

我需要有关此代码的帮助,因此,如果有人愿意提供帮助,我将不胜感激。

我创建了一个简单的线程池,它传递了一个数字数组,对于每个数字,线程需要计算该数字的阶乘。对我来说有什么问题,如果我创建了一个 2 个线程的线程池,第一个线程将执行第一个任务,第二个线程将执行第二个任务,问题是如果在特定情况下有两个以上的任务,这些线程不会唤醒执行所有任务, 问题是我不知道如何重新唤醒线程,以及如何让它们在有任务的情况下继续执行任务?

这是我的代码:

MyThreadPool 类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ThreadPool
{
    public class MyThreadPool
    {
        private bool _disposed = false;
        private object _lock = new object();
        private Queue<MyTask> tasks = new();
        private List<Thread> threads = new();
        public MyThreadPool(int numThreads = 0)
        {
            
            for (int i = 0; i < numThreads; i++)
            {
                new Thread(() =>
                {
                    threads.Add(Thread.CurrentThread);
                    if (_disposed == false)
                    {
                        MyTask task = null;
                        lock (_lock)
                        {

                            if (tasks.Count > 0)
                            {
                                task = tasks.Dequeue();

                            }
                            else
                                _disposed = true;

                            if (task != null)
                            {
                                Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} calculated factorial for {task.getNum()}. Result: {task.CalculateFactoriel(task.getNum())}");
                                Thread.Sleep(1000);
                            }
                            else
                            {
                                Thread.Sleep(1000);

                            }
                        }

                    }


                }).Start();
            }
       
        }
        public void Enqueue(int number)
        {
            tasks.Enqueue(new MyTask(number));
        }
        public void Dispose()
        {
            if (_disposed == true)
            {
                foreach (Thread thread in threads)
                {
                    thread.Join();
                }
            }
        }

    }
}

MyTask 类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ThreadPool
{
    public class MyTask
    {
        private int num;
        public void setNum(int num)
        {
            this.num = num;
        }
        public int getNum()
        {
            return this.num;
        }
        public MyTask(int number)
        {
            this.num = number;
            
        }
        public int CalculateFactoriel(int number)
        {
            int result = 1;
            for (int i = number; i > 0; i--)
            { 
                result = result * i;
            }
            return result;
        }

    }
}

程序.cs:

int[] array = { 1, 2, 3, 4, 5, 6 };
int numThread = 2;
int x = 0;
MyThreadPool threadPool = new(numThread);
for (int i = 0; i < array.Length; i++)
{
    threadPool.Enqueue(array[i]);

}
while (x != array.Length) ;


threadPool.Dispose();
C# 多线程线程池线程 睡眠 唤醒

评论

1赞 Magnus 11/11/2023
这是出于教育目的吗?或者为什么需要自定义线程池?
0赞 SP222 11/11/2023
这是出于教育目的,了解线程的工作原理等
0赞 Marc Gravell 11/11/2023
第一次无事可做,意味着事情会退出——如果消费超过供应,这就是问题所在吗?通常,如果队列为空,我希望看到一个 Monitor.Wait,每当添加并且队列为空时,我都会看到一个 Monitor.PulseAll - Pulse/PulseAll 唤醒一个在等待中休眠的线程。然而,老实说,在这里运行自己的线程池似乎有点矫枉过正。我只是 Task.Run 其中的很多!_disposed = true;
0赞 Enigmativity 11/13/2023
粗略地看了一下,我发现这是一个非线程安全的调用。threads.Add(Thread.CurrentThread);

答: 暂无答案