1.Atomic的原子自增運算
1.
最好將thread.activeCount的值擴大一點兒,因為過小的話會導致記憶體切換的過於頻繁,容易導致程式崩潰
執行結果如下:
程式碼原始碼:
import org.omg.PortableServer.THREAD_POLICY_ID; import java.util.concurrent.atomic.AtomicInteger; /** * Atomic變數自增運算測試 */ public class AtomicTest { public static AtomicInteger race = new AtomicInteger(0); public static void increase() { race.incrementAndGet(); } private static final int THREADS_COUNT = 20; public static void main(String[] args) throws Exception { Thread[] threads = new Thread[THREADS_COUNT]; //定義一組threas的陣列集合 for (int i = 0; i < THREADS_COUNT; i++) { //20個執行緒進行單個迴圈 threads[i] = new Thread(new Runnable() { //單個執行緒進行實現runable的操作 @Override public void run() { for (int i = 0; i < 10000; i++){ increase(); //對increase進行自增操作,執行結果如下,內部迭代的工程 } } }); //啟動當前狀態的i執行緒,因此要寫在for迴圈裡面 threads[i].start(); } while(Thread.activeCount()>10); Thread.yield(); System.out.println(race);//正確輸出結果為10000(單個程序自增的次數)*20(總的程序數) //因此自增結果應該為200000,但是實際結果並不是,而是偏小 } }
先得出輸出結果,如下;
程式碼如下:
import org.omg.PortableServer.THREAD_POLICY_ID; import java.util.concurrent.atomic.AtomicInteger; /** * Atomic變數自增運算測試 */ public class AtomicTest { //public static AtomicInteger race = new AtomicInteger(0); public static int race = 1; public static void increase() { race++; } private static final int THREADS_COUNT = 20; public static void main(String[] args) throws Exception { Thread[] threads = new Thread[THREADS_COUNT]; //定義一組threas的陣列集合 for (int i = 0; i < THREADS_COUNT; i++) { //20個執行緒進行單個迴圈 threads[i] = new Thread(new Runnable() { //單個執行緒進行實現runable的操作 @Override public void run() { for (int i = 0; i < 100; i++){ increase(); //對increase進行自增操作,執行結果如下,內部迭代的工程 } } }); //啟動當前狀態的i執行緒,因此要寫在for迴圈裡面 threads[i].start(); } while(Thread.activeCount()>4); //Thread.yield(); System.out.println(race);//正確輸出結果為100(單個程序自增的次數)*20(總的程序數) //因此自增結果應該為2000,但是實際結果並不是,而是偏小 } }
//因此可知這種方法也是執行緒相對而言,並不是安全的。
但是AntomicInteger操作之後:
如下:
得出了正確的結果:
程式碼原始碼如下:
import org.omg.PortableServer.THREAD_POLICY_ID; import java.util.concurrent.atomic.AtomicInteger; /** * Atomic變數自增運算測試 */ public class AtomicTest { public static AtomicInteger race = new AtomicInteger(0); public static void increase() { race.incrementAndGet(); } private static final int THREADS_COUNT = 20; public static void main(String[] args) throws Exception { Thread[] threads = new Thread[THREADS_COUNT]; //定義一組threas的陣列集合 for (int i = 0; i < THREADS_COUNT; i++) { //20個執行緒進行單個迴圈 threads[i] = new Thread(new Runnable() { //單個執行緒進行實現runable的操作 @Override public void run() { for (int i = 0; i < 100; i++){ increase(); //對increase進行自增操作,執行結果如下,內部迭代的工程 } } }); //啟動當前狀態的i執行緒,因此要寫在for迴圈裡面 threads[i].start(); } while(Thread.activeCount()>2); //Thread.yield(); System.out.println(race);//正確輸出結果為100(單個程序自增的次數)*20(總的程序數) //因此自增結果應該為2000,但是實際結果並不是,而是偏小 } }
使用int進行定義的時候,race這是不安全的機制,詳細程式碼,可以複製拿去驗證,但是使用AtomicInteger盡享定義就不一樣的了,因為其定義了race之後,呼叫方法,incrementAndGet()方法,但是該方法是原子性的可以確保其執行緒是安全的。
驗證的時候,Thread.activeCount>不要設定的過大。這個
問題會專門寫個專題擴充套件一下:
Thread.activeCount() 方法返回活動執行緒的當前執行緒的執行緒組中的數量,已你現在的程式(執行緒中間過程短,一下就結束了)所以你Thread.activeCount()時為1,你可以System.out.println(Thread.activeCount())控制檯輸出試試
1的話,當前執行緒組的書,數目為1,是會導致切換過快,計算機進行假死的情況的。
因此需要設定成2以及以上即可。
其中incrementAndGet()方法,跟進去,檢視如下所示:
繼承了Number類以及進行了序列化的操作:
final表明了這個是不可能輕易被繼承的,一定程度保證了其原子性
然後再跟進一個getAndAddInt繼續去跟進下一步:
對於getIntVolatile()這個方法進行跟進如下所示;
擴充套件如下所示:
1。native 是用做java 和其他語言(如c++)進行協作時用的
也就是native 後的函式的實現不是用java寫的
2。既然都不是java,那就別管它的原始碼了