更轻量级的Semaphore、AutoResetEvent、ThreadPool

内部完全使用Monitor实现,理论上比使用WaitHandler的资源消耗更少,也更快。缺点是会损失一些功能。

Semaphore源码(btw:gotdotnet上面有一个ManagedThreadPool):
 1 using  System;
 2 using  System.Threading;
 3
 4 namespace  newsmth.Nineteen
 5 {
 6    public class SemaphoreLite
 7    {
 8        private int _count;
 9        private object _sem = new object();
10
11        ctor.#region ctor.
12        public SemaphoreLite(int count)
13        {
14            _count = count;
15        }

16        #endregion

17
18        methods#region methods
19        public bool Wait()
20        {
21            return Wait(Timeout.Infinite);
22        }

23
24        public bool Wait(int millisecondsTimeout)
25        {
26            if (millisecondsTimeout < 0 && millisecondsTimeout != Timeout.Infinite)
27            {
28                throw new ArgumentOutOfRangeException("millisecondsTimeout 值应该大于0或等于Timeout.Infinite。");
29            }

30
31            lock (_sem)
32            {
33                if (_count <= 0)
34                {
35                    if (!Monitor.Wait(_sem, millisecondsTimeout))
36                    {
37                        return false;
38                    }

39                }

40                _count--;
41                return true;
42            }

43        }

44
45        public void WaitUntil(int amount)
46        {
47            lock (_sem)
48            {
49                while (_count < amount)
50                {
51                    Monitor.Wait(_sem, Timeout.Infinite);
52                }

53                _count = _count - amount;
54            }

55
56        }

57
58        public void Pulse()
59        {
60            lock (_sem)
61            {
62                _count++;
63                Monitor.Pulse(_sem);
64            }

65        }

66        #endregion

67    }

68}

69
70

AutoResetEvent源码:
 1 using  System;
 2 using  System.Threading;
 3
 4 namespace  newsmth.Nineteen
 5 {
 6    public class AutoResetEventLite
 7    {
 8        private object _sem = new object();
 9        private bool _isSet;
10
11        private static int id = 0;
12        private int _currentId;
13
14        public methods#region public methods
15        public int ID
16        {
17            get return _currentId; }
18        }

19
20        public AutoResetEventLite(bool initialState)
21        {
22            if (initialState)
23            {
24                _isSet = true;
25            }

26            else
27            {
28                _isSet = false;
29            }

30            Interlocked.Exchange(ref _currentId, id);
31            Interlocked.Increment(ref id);            
32        }

33
34        public bool Wait()
35        {
36            return Wait(Timeout.Infinite);
37        }

38
39        public bool Wait(int millisecondsTimeout)
40        {
41            if (millisecondsTimeout < 0 && millisecondsTimeout != Timeout.Infinite)
42            {
43                throw new ArgumentOutOfRangeException("millisecondsTimeout 参数应该大于0或等于Timeout.Infinite。");
44            }

45
46            lock (_sem)
47            {
48                bool result;
49                
50                if (!_isSet)
51                {
52                    result = Monitor.Wait(_sem, millisecondsTimeout);
53                    if (!result)
54                    {
55                        return false;
56                    }

57                }

58                _isSet = false;
59                return true;
60            }

61        }

62
63        public void Set()
64        {
65            lock (_sem)
66            {
67                if (_isSet)
68                {
69                    return;
70                }

71                Monitor.Pulse(_sem);
72                _isSet = true;
73            }

74        }

75        #endregion

76
77    }

78}

79
80

ThreadPool:
大家都知道,计算密集型应用和IO密集型应用很不同。
对计算密集型的应用,首先要保持活动线程有合适的数量,少了,多cpu机器有些cpu会闲,多了,丫又会做很多无用功在线程上下文切换上;其次,应该尽可能减少活动线程在等待某些条件时的上下文切换(如果这些条件出现非常频繁迅速的话),即用SpinWait并不断轮询,而不是Sleep或者等一个WaitHandler。
IO密集型则不同,一般情况下,这东西就跟放掉水池里的水,出水口越多,放的就越快。

说它只是个半成品,是只实现了这么一个架子,没有做什么优化,也没经过很好的测试。效率,俺猜,应该不比系统的线程池差。code project上有个功能爆强的ThreadPool,但是它是建立在WaitHandler上的。尽管“只有适合自己的才是最好的”,但是它的代码还是很推荐一读。

btw:多说两句ThreadPool中两个很关键但是很简单的数据结构,一,任务被压到ThreadPool中应该是先进先出的队列;线程的调度,应该是后进先出的stack。后者,让忙的线程更忙,闲的线程更闲,是保持活动线程数更小的重要手段,不幸的是,它常常被忽略。
  1 using  System;
  2 using  System.Collections.Generic;
  3 using  System.Text;
  4 using  System.Threading;
  5
  6 namespace  newsmth.Nineteen
  7 {
  8    //根据需求,可以改成非static的,可以增加管理功能,可以依据计算密集型应用、IO密集型应用作出不同优化等等等等
  9    public static class ThreadPoolLite
 10    {
 11        
 12        public static readonly int MaxThreadCount = Environment.ProcessorCount * 2 + 2;
 13        public static readonly int InitThreadCount = Environment.ProcessorCount;
 14        public static readonly int MaxQueueLength = Environment.ProcessorCount * 2 + 2;
 15        private const int MaxMillisecondsTimeoutToQueueItem = 30000;
 16        private const int MaxMillisecondsTimeoutToKillWorker = 180000;
 17        private const int MaxMillisecondsTimeoutWaitingForWorker = 3000;
 18
 19        private static Stack<AutoResetEventLite> _threads = new Stack<AutoResetEventLite>();
 20        private static Queue<WorkItem> _workItems = new Queue<WorkItem>();
 21
 22        //queue's empty count.
 23        private static SemaphoreLite _queueSemR = new SemaphoreLite(MaxQueueLength);
 24        //queue's count. 
 25        private static SemaphoreLite _queueSemP = new SemaphoreLite(0);
 26        private static SemaphoreLite _threadP = new SemaphoreLite(0);
 27
 28        private static int _aliveThreads = 0;
 29        public static int AliveThreads
 30        {
 31            get
 32            {
 33                return _aliveThreads;
 34            }

 35        }

 36
 37        public static int CurrentQueueLength
 38        {
 39            get return _workItems.Count; }
 40        }

 41
 42        static ThreadPoolLite()
 43        {
 44            Thread dispatcher = new Thread(new ThreadStart(Dispatcher));
 45            dispatcher.IsBackground = true;
 46            dispatcher.Start();
 47
 48            for (int i = 0; i < InitThreadCount; i++)
 49            {
 50                AddNewThread();
 51            }

 52        }

 53
 54        public static bool QueueWorkItem(WaitCallback waitCallback)
 55        {
 56            return QueueWorkItem(waitCallback, null);
 57        }

 58
 59        public static bool QueueWorkItem(WaitCallback waitCallback, object state)
 60        {
 61            if (waitCallback == null)
 62            {
 63                throw new ArgumentNullException("waitCallback");
 64            }

 65
 66            WorkItem item = new WorkItem(waitCallback, state);
 67
 68            //wait for the queue.
 69            if (_queueSemR.Wait(MaxMillisecondsTimeoutToQueueItem))
 70            {
 71                lock (_workItems)
 72                {
 73                    _workItems.Enqueue(item);
 74                }

 75                _queueSemP.Pulse();
 76                return true;
 77            }

 78            else
 79            {
 80                return false;
 81            }

 82        }

 83
 84        private methods#region private methods
 85        private static void Worker(object state)
 86        {
 87            AutoResetEventLite are = (AutoResetEventLite)state;
 88            while (are.Wait(MaxMillisecondsTimeoutToKillWorker))
 89            {
 90                WorkItem item;
 91                lock (_workItems)
 92                {
 93                    item = _workItems.Dequeue();
 94                }

 95                _queueSemR.Pulse();
 96
 97                //不考虑线程上下文的改变
 98                try
 99                {
100                    item.WaitCallback(item.State);
101                }

102                catch
103                {
104                    //是不是要扔个异步事件出去再说.
105                    continue;
106                }

107                finally
108                {
109                    lock (_threads)
110                    {
111                        _threads.Push(are);
112                        _threadP.Pulse();
113                    }

114
115                    if (AliveThreads == ThreadPoolLite.MaxThreadCount)
116                    {
117                        Thread.Sleep(0);
118                    }

119                }

120            }

121
122            lock (_threads)
123            {
124                if (are.Wait(0))
125                {
126                    //中了五百万
127                    _queueSemP.Pulse();
128                }

129                Interlocked.Decrement(ref _aliveThreads);
130                //压缩stack
131                Stack<AutoResetEventLite> tmp = new Stack<AutoResetEventLite>();
132                while (_threads.Count > 0)
133                {
134                    AutoResetEventLite areT = _threads.Pop();
135                    if (object.ReferenceEquals(areT, are))//感觉好多了
136                    {
137                        continue;
138                    }

139                    tmp.Push(areT);
140                }

141                _threads.Clear();
142                while (tmp.Count > 0)
143                {
144                    _threads.Push(tmp.Pop());
145                }

146            }

147        }

148
149        private static void Dispatcher()
150        {
151            while (true)
152            {
153                _queueSemP.Wait();
154                if (_threads.Count != 0)
155                {
156                    ActiveThread();
157                    continue;
158                }

159                else
160                {
161                    if (_threadP.Wait(MaxMillisecondsTimeoutWaitingForWorker))
162                    {
163                        ActiveThread();
164                        continue;
165                    }

166                    else
167                    {
168                        if (AliveThreads < MaxThreadCount)
169                        {
170                            AddNewThread();
171                            ActiveThread();
172                            continue;
173                        }

174                        else
175                        {
176                            _threadP.Wait();
177                            ActiveThread();
178                            continue;
179                        }

180                    }

181                }

182            }

183        }

184
185        private static void ActiveThread()
186        
187            _threadP.Wait();
188
189            AutoResetEventLite are;
190            lock (_threads)
191            {
192                are = _threads.Pop();
193                are.Set();
194            }

195            //Thread.Sleep(1);
196        }

197
198        private static void AddNewThread()
199        {
200            AutoResetEventLite are = new AutoResetEventLite(false);
201            Thread t = new Thread(new ParameterizedThreadStart(Worker));
202            t.IsBackground = true;
203            t.Start(are);
204            Interlocked.Increment(ref _aliveThreads);
205            lock (_threads)
206            {
207                _threads.Push(are);
208            }

209            _threadP.Pulse();
210        }

211        #endregion

212
213        WorkItem#region WorkItem
214        private class WorkItem
215        {
216            public WorkItem(WaitCallback waitCallback, object state)
217            {
218                _waitCallback = waitCallback;
219                _state = state;
220            }

221
222            private WaitCallback _waitCallback;
223            public WaitCallback WaitCallback
224            {
225                get return _waitCallback; }
226            }

227
228            private object _state;
229            public object State
230            {
231                get return _state; }
232            }

233        }

234        #endregion

235    }

236}

237
238

欢迎拍砖。

你可能感兴趣的:(更轻量级的Semaphore、AutoResetEvent、ThreadPool)