天天看點

原子循環計數器

感謝同僚[孫棋]的投稿

現實當中很多場景,需要進行輪訓服務,比如輪訓在10個日志檔案當中寫日志,在10台機器上輪訓的去調用以實作負載均衡,正常的做法,如tomcat的poller線程輪訓選擇,就采用

<code>1</code>

<code>math.abs(pollerrotater.incrementandget()) % pollers.length</code>

此地需要取原子自增的絕對值模以poller線程數,那是否有更好的實作呢?

<code>01</code>

<code>public</code> <code>class</code> <code>cycleatomicinteger {</code>

<code>02</code>

<code>private</code> <code>final</code> <code>static</code> <code>long</code> <code>park_time = 1000l *</code><code>1000</code><code>;</code>

<code>03</code>

<code>04</code>

<code>private</code> <code>atomicinteger counter =</code><code>new</code> <code>atomicinteger(</code><code>0</code><code>);</code>

<code>05</code>

<code>06</code>

<code>private</code> <code>int</code> <code>range;</code>

<code>07</code>

<code>08</code>

<code>public</code> <code>cycleatomicinteger(</code><code>int</code> <code>range) {</code>

<code>09</code>

<code>    </code><code>if</code> <code>(range &amp;lt;</code><code>2</code><code>)</code>

<code>10</code>

<code>        </code><code>throw</code> <code>new</code> <code>illegalargumentexception();</code>

<code>11</code>

<code>    </code><code>this</code><code>.range = range;</code>

<code>12</code>

<code>}</code>

<code>13</code>

<code>14</code>

<code>/**</code>

<code>15</code>

<code> </code><code>* 擷取下個原子值</code>

<code>16</code>

<code> </code><code>*</code>

<code>17</code>

<code> </code><code>* @return</code>

<code>18</code>

<code> </code><code>*/</code>

<code>19</code>

<code>public</code> <code>int</code> <code>next() {</code>

<code>20</code>

<code>    </code><code>for</code> <code>(;;) {</code>

<code>21</code>

<code>        </code><code>int</code> <code>c = counter.get();</code>

<code>22</code>

<code>        </code><code>int</code> <code>next = (c +</code><code>1</code><code>) % range;</code>

<code>23</code>

<code>        </code><code>if</code> <code>(counter.compareandset(c, next)) {</code>

<code>24</code>

<code>            </code><code>return</code> <code>c;</code>

<code>25</code>

<code>        </code><code>}</code><code>else</code> <code>{</code>

<code>26</code>

<code>            </code><code>locksupport.parknanos(park_time);</code>

<code>27</code>

<code>        </code><code>}</code>

<code>28</code>

<code>    </code><code>}</code>

<code>29</code>

<code>30</code>

<code>31</code>

這樣就可以快速的實作rr的效果,同時也避免了abs的過程,至于locksupport.parknanos(park_time);加了這個後,4個線程執行2億次的計算,我本機從原來的16s減少到4s,至于為什麼要加這個,可參見更快的atomicinteger

當然,這樣設計會存在cas的aba問題,但對目前的case需求,其實是滿足的,也不存在問題

繼續閱讀