C#有ThreadPool和Task,为什么还要自己写线程池?我以前也没想过自己写线程池,都是用ThreadPool或Task,前段时间写爬虫,我想控制10个线程爬网页、10个线程下载网页上的图片,不然的话因为网页很多,图片相对较少,可能大部分线程都在爬网页,少量线程在下载图片,这样下载图片的速度慢了,所以我想到了自己写线程池MyThreadPool,再配合ThreadPool使用,精确控制爬网页和下载图片的线程数。不过这个线程池写的比较简单,缺点是线程池会瞬间创建最大数量的工作线程。
线程池类代码:
using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace Utils { /// <summary> /// 线程池 /// </summary> public static class MyThreadPool { /// <summary> /// 最大工作线程数 /// </summary> private static int m_WorkerThreads = 5; /// <summary> /// 线程队列 /// </summary> private static ConcurrentQueue<MyThread> m_ThreadQueue = new ConcurrentQueue<MyThread>(); /// <summary> /// 任务队列 /// </summary> private static ConcurrentQueue<Tuple<Action<object>, object>> m_Action = new ConcurrentQueue<Tuple<Action<object>, object>>(); /// <summary> /// 创建并启动线程 /// </summary> /// <param name="action"></param> /// <param name="obj"></param> public static void Start(Action<object> action, object obj = null) { m_Action.Enqueue(new Tuple<Action<object>, object>(action, obj)); MyThread thread; if (m_ThreadQueue.Count < m_WorkerThreads) { thread = new MyThread(); m_ThreadQueue.Enqueue(thread); thread.isWorker = true; //设置为工作线程 thread.thread = new Thread(new ThreadStart(() => { Tuple<Action<object>, object> tuple; while (thread.isWorker) //如果是工作线程,则一直循环 { if (m_Action.TryDequeue(out tuple)) //如果任务队列中有任务,则取出任务执行 { tuple.Item1(tuple.Item2); //执行任务 } else { Thread.Sleep(100); } Thread.Sleep(1); } })); thread.thread.IsBackground = true; thread.thread.Start(); } } /// <summary> /// 设置最大工作线程数 /// </summary> /// <param name="workerThreads">最大工作线程数</param> public static void SetMaxThreads(int workerThreads) { m_WorkerThreads = workerThreads; MyThread thread = null; while (m_ThreadQueue.Count > m_WorkerThreads) { m_ThreadQueue.TryDequeue(out thread); thread.isWorker = false; Thread.Sleep(1); } } /// <summary> /// 获取最大工作线程数 /// </summary> public static int GetMaxThreads() { return m_WorkerThreads; } /// <summary> /// 获取当前工作线程数 /// </summary> public static int GetWorkerThreads() { return m_ThreadQueue.Count; } } /// <summary> /// 线程 /// </summary> public class MyThread { /// <summary> /// 线程 /// </summary> public Thread thread { get; set; } /// <summary> /// 是否工作线程 /// </summary> public bool isWorker { get; set; } } }