简单ThreadPool实现
由于最近需要用多线程处理一些问题,一开始我用了.net默认的ThreadPool,感觉不是很适合。于是我自己实现了一个简单的ThreadPool。
写的比较简单,有兴趣的朋友一起看看,共同改进。
代码主要由ThreadPoolEx,WorkItem,WorkQueue组成。
由于最近需要用多线程处理一些问题,一开始我用了.net默认的ThreadPool,感觉不是很适合。于是我自己实现了一个简单的ThreadPool。
写的比较简单,有兴趣的朋友一起看看,共同改进。
代码主要由ThreadPoolEx,WorkItem,WorkQueue组成。
推荐使用新版本:http://www.cnblogs.com/ITAres/archive/2009/08/25/1553800.html
ThreadPoolEx
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Threading;
6using System.Collections;
7
8namespace NetDragon.ThreadPoolEx
9{
10 public class ThreadPoolEx
11 {
12 private WorkQueue _workQueue = new WorkQueue();
13
14 public int MaxThreadCount = 10;
15 public int MinThreadCount = 2;
16 private Hashtable _threadTable = null;
17
18 private int _threadCount = 0;
19 private int _inUseWorkThread = 0;
20
21 public double IdleTimeout = 10;
22
23 public ThreadPoolEx():this(10,2,2)
24 {
25 }
26
27 public ThreadPoolEx(int maxThreadCouont, int minThreadCount, int idleTimeout)
28 {
29 MaxThreadCount = maxThreadCouont;
30
31 MinThreadCount = minThreadCount;
32
33 IdleTimeout = idleTimeout;
34
35 _threadTable = Hashtable.Synchronized(new Hashtable(MaxThreadCount));
36 }
37
38 public void QueueUserWorkItem(WaitCallback waitCallback, object objParams)
39 {
40 EnqueueWorkItem(waitCallback, objParams);
41 }
42
43 private void EnqueueWorkItem(WaitCallback waitCallback,object objParams)
44 {
45 WorkItem workItem = new WorkItem() {
46
47 WorkCallback = waitCallback,
48 ObjParams = objParams
49 };
50
51 _workQueue.Push(workItem);
52
53 if (_inUseWorkThread + _waitWorkItem > _threadTable.Count)
54 {
55 StartThread();
56 }
57 }
58
59 private void StartThread()
60 {
61 if (_threadTable.Count < MaxThreadCount)
62 {
63 ++_threadCount;
64
65 Thread thread = new Thread(ProcessWorkItems);
66
67 thread.IsBackground = true;
68
69 thread.Name = "ThreadPoolEx #" + _threadCount;
70
71 thread.Priority = ThreadPriority.Normal;
72
73 _threadTable[thread] = System.DateTime.Now;
74
75 thread.Start();
76 }
77 }
78
79 private void ProcessWorkItems()
80 {
81
82 try
83 {
84 while (true)
85 {
86 WorkItem workItem = _workQueue.Pop();
87
88 if (workItem == null)
89 {
90 bool isTimeout = CurThreadIsTimeOut();
91
92 if (isTimeout)
93 {
94 if (_threadTable.Count > MinThreadCount)
95 {
96 _threadTable.Remove(Thread.CurrentThread);
97 break;
98 }
99 }
100
101 System.Threading.Thread.Sleep(100);
102 }
103 else
104 {
105
106 try
107 {
108 _threadTable[Thread.CurrentThread] = System.DateTime.Now;
109 Interlocked.Increment(ref _inUseWorkThread);
110
111 workItem.Execute();
112 }
113 catch (Exception)
114 {
115 // log something
116 }
117 finally
118 {
119 Interlocked.Decrement(ref _inUseWorkThread);
120 }
121 }
122 }
123 }
124 catch (ThreadAbortException)
125 {
126 Thread.ResetAbort();
127 }
128 finally
129 {
130 if (_threadTable.Contains(Thread.CurrentThread))
131 {
132 _threadTable.Remove(Thread.CurrentThread);
133 }
134 }
135 }
136
137 private bool CurThreadIsTimeOut()
138 {
139 DateTime lastAliveTime = (DateTime)_threadTable[Thread.CurrentThread];
140
141 DateTime curTime = System.DateTime.Now;
142
143 double waitSeconds = (curTime - lastAliveTime).TotalSeconds;
144
145 if(waitSeconds > IdleTimeout)
146 {
147 return true;
148 }
149
150 return false;
151
152 }
153
154 private int _waitWorkItem
155 {
156 get
157 {
158 return _workQueue.Count;
159 }
160 }
161
162 public int ThreadCount
163 {
164 get
165 {
166 return _threadTable.Count;
167 }
168 }
169 }
170}
171
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Threading;
6using System.Collections;
7
8namespace NetDragon.ThreadPoolEx
9{
10 public class ThreadPoolEx
11 {
12 private WorkQueue _workQueue = new WorkQueue();
13
14 public int MaxThreadCount = 10;
15 public int MinThreadCount = 2;
16 private Hashtable _threadTable = null;
17
18 private int _threadCount = 0;
19 private int _inUseWorkThread = 0;
20
21 public double IdleTimeout = 10;
22
23 public ThreadPoolEx():this(10,2,2)
24 {
25 }
26
27 public ThreadPoolEx(int maxThreadCouont, int minThreadCount, int idleTimeout)
28 {
29 MaxThreadCount = maxThreadCouont;
30
31 MinThreadCount = minThreadCount;
32
33 IdleTimeout = idleTimeout;
34
35 _threadTable = Hashtable.Synchronized(new Hashtable(MaxThreadCount));
36 }
37
38 public void QueueUserWorkItem(WaitCallback waitCallback, object objParams)
39 {
40 EnqueueWorkItem(waitCallback, objParams);
41 }
42
43 private void EnqueueWorkItem(WaitCallback waitCallback,object objParams)
44 {
45 WorkItem workItem = new WorkItem() {
46
47 WorkCallback = waitCallback,
48 ObjParams = objParams
49 };
50
51 _workQueue.Push(workItem);
52
53 if (_inUseWorkThread + _waitWorkItem > _threadTable.Count)
54 {
55 StartThread();
56 }
57 }
58
59 private void StartThread()
60 {
61 if (_threadTable.Count < MaxThreadCount)
62 {
63 ++_threadCount;
64
65 Thread thread = new Thread(ProcessWorkItems);
66
67 thread.IsBackground = true;
68
69 thread.Name = "ThreadPoolEx #" + _threadCount;
70
71 thread.Priority = ThreadPriority.Normal;
72
73 _threadTable[thread] = System.DateTime.Now;
74
75 thread.Start();
76 }
77 }
78
79 private void ProcessWorkItems()
80 {
81
82 try
83 {
84 while (true)
85 {
86 WorkItem workItem = _workQueue.Pop();
87
88 if (workItem == null)
89 {
90 bool isTimeout = CurThreadIsTimeOut();
91
92 if (isTimeout)
93 {
94 if (_threadTable.Count > MinThreadCount)
95 {
96 _threadTable.Remove(Thread.CurrentThread);
97 break;
98 }
99 }
100
101 System.Threading.Thread.Sleep(100);
102 }
103 else
104 {
105
106 try
107 {
108 _threadTable[Thread.CurrentThread] = System.DateTime.Now;
109 Interlocked.Increment(ref _inUseWorkThread);
110
111 workItem.Execute();
112 }
113 catch (Exception)
114 {
115 // log something
116 }
117 finally
118 {
119 Interlocked.Decrement(ref _inUseWorkThread);
120 }
121 }
122 }
123 }
124 catch (ThreadAbortException)
125 {
126 Thread.ResetAbort();
127 }
128 finally
129 {
130 if (_threadTable.Contains(Thread.CurrentThread))
131 {
132 _threadTable.Remove(Thread.CurrentThread);
133 }
134 }
135 }
136
137 private bool CurThreadIsTimeOut()
138 {
139 DateTime lastAliveTime = (DateTime)_threadTable[Thread.CurrentThread];
140
141 DateTime curTime = System.DateTime.Now;
142
143 double waitSeconds = (curTime - lastAliveTime).TotalSeconds;
144
145 if(waitSeconds > IdleTimeout)
146 {
147 return true;
148 }
149
150 return false;
151
152 }
153
154 private int _waitWorkItem
155 {
156 get
157 {
158 return _workQueue.Count;
159 }
160 }
161
162 public int ThreadCount
163 {
164 get
165 {
166 return _threadTable.Count;
167 }
168 }
169 }
170}
171
WorkItem
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Threading;
6
7namespace NetDragon.ThreadPoolEx
8{
9 class WorkItem
10 {
11 public WaitCallback WorkCallback;
12
13 public object ObjParams;
14
15 public void Execute()
16 {
17 WorkCallback(ObjParams);
18 }
19 }
20}
21
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Threading;
6
7namespace NetDragon.ThreadPoolEx
8{
9 class WorkItem
10 {
11 public WaitCallback WorkCallback;
12
13 public object ObjParams;
14
15 public void Execute()
16 {
17 WorkCallback(ObjParams);
18 }
19 }
20}
21
WorkQueue
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5
6namespace NetDragon.ThreadPoolEx
7{
8 class WorkQueue
9 {
10 private static object threadLock = new object();
11
12 private Queue<WorkItem> _workQueue = new Queue<WorkItem>();
13
14 public WorkItem Pop()
15 {
16 lock (threadLock)
17 {
18 if (_workQueue.Count > 0)
19 {
20 return _workQueue.Dequeue();
21 }
22 return null;
23 }
24 }
25
26
27 public void Push(WorkItem workItem)
28 {
29 lock (threadLock)
30 {
31 _workQueue.Enqueue(workItem);
32
33 }
34 }
35
36 public int Count
37 {
38 get
39 {
40 return _workQueue.Count;
41 }
42 }
43 }
44}
45
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5
6namespace NetDragon.ThreadPoolEx
7{
8 class WorkQueue
9 {
10 private static object threadLock = new object();
11
12 private Queue<WorkItem> _workQueue = new Queue<WorkItem>();
13
14 public WorkItem Pop()
15 {
16 lock (threadLock)
17 {
18 if (_workQueue.Count > 0)
19 {
20 return _workQueue.Dequeue();
21 }
22 return null;
23 }
24 }
25
26
27 public void Push(WorkItem workItem)
28 {
29 lock (threadLock)
30 {
31 _workQueue.Enqueue(workItem);
32
33 }
34 }
35
36 public int Count
37 {
38 get
39 {
40 return _workQueue.Count;
41 }
42 }
43 }
44}
45