AtomicInteger這個類的存在是為了滿足在高並發的情況下,原生的整形數值自增線程不安全的問題。比如說
int i = 0 ; i++;
- 1
- 2
上面的寫法是線程不安全的。
有的人可能會說了,可以使用synchronized關鍵字啊。
但是這里筆者要說的是,使用了synchronized去做同步的話系統的性能將會大大下降。
所以此時AtomicInteger這個類的使用就可以滿足上述的情況。
當我們統計一個頁面的瀏覽量的時候,可以使用該類來統計,而不再使用++運算符。
但是在使用的過程中,筆者發現,使用++運算符和AtomicInteger的結果都是對的。。。
結果有點暈了,難道結論是錯的么?當然不是了。
注意這個類使用的情況下是在高並發量的情況下。不是同時啟10個20個線程,而是成千上萬個線程。
我們先看看AtomicInteger類起作用的代碼
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; public class AtomicIntegerTest { public static final AtomicInteger atomicInteger = new AtomicInteger(0); public static void main(String[] args) throws InterruptedException { atomicIntegerTest(); Thread.sleep(3000); System.out.println("最終結果是" + atomicInteger.get()); } private static void atomicIntegerTest() { ExecutorService executorService = Executors.newFixedThreadPool(10000); for (int i = 0; i < 10000; i++) { executorService.execute(() -> { for (int j = 0; j < 4; j++) { System.out.println(atomicInteger.getAndIncrement()); } }); } executorService.shutdown(); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
打印的結果是4萬
再看看++操作符
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class IntValueIncrementTest { public static int value = 0; public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newFixedThreadPool(10000); for (int i = 0; i < 10000; i++) { executorService.execute(() -> { for (int j = 0; j < 4; j++) { System.out.println(value++); } }); } executorService.shutdown(); Thread.sleep(3000); System.out.println("最終結果是" + value); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
我們可以看到結果是39972,顯然結果丟失了一些。
所以在高並發的情況下應當使用AtomicInteger類
當我們在並發情況下,但是並發量又不是那么大的時候,
我們將上述的代碼改掉,改為同時只有10個線程在修改數值。
我們貼代碼
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; public class AtomicIntegerTest { public static final AtomicInteger atomicInteger = new AtomicInteger(0); public static void main(String[] args) throws InterruptedException { atomicIntegerTest(); Thread.sleep(3000); System.out.println("最終結果是" + atomicInteger.get()); } private static void atomicIntegerTest() { ExecutorService executorService = Executors.newFixedThreadPool(10000); for (int i = 0; i < 10; i++) { executorService.execute(() -> { for (int j = 0; j < 4; j++) { System.out.println(atomicInteger.getAndIncrement()); } }); } executorService.shutdown(); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
運行的結果是40
再貼10個線程的並發量的情形。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class IntValueIncrementTest { public static int value = 0; public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newFixedThreadPool(10000); for (int i = 0; i < 10; i++) { executorService.execute(() -> { for (int j = 0; j < 4; j++) { System.out.println(value++); } }); } executorService.shutdown(); Thread.sleep(3000); System.out.println("最終結果是" + value); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
發現此時的結果也是40。
所以這就給人一種假象:
1)AtomicInteger類不起作用.
2)i++或者++i是線程安全的
其實上面兩點觀念都是錯誤的。是因為並發量不夠高而已
但是需要注意的是AtomicInteger類只能保證在自增或者自減的情況下保證線程安全
轉自 https://blog.csdn.net/u013803262/article/details/72452932