感謝同僚[孫棋]的投稿
現實當中很多場景,需要進行輪訓服務,比如輪訓在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 &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需求,其實是滿足的,也不存在問題