java 原子量_Java原子量 - Rickxue的个人空间 - OSCHINA - 中文开源技术交流社区
所謂的原子量即操作變量的操作是“原子的”,該操作不可再分,因此是線程安全的。
為何要使用原子變量呢,原因是多個線程對單個變量操作也會引起一些問題。在Java5之前,可以通過volatile、synchronized關鍵字來解決并發訪問的安全問題,但這樣太麻煩。
Java5之后,專門提供了用來進行單變量多線程并發安全訪問的工具包java.util.concurrent.atomic,其中的類也很簡單。
下面給出一個反面例子(切勿模仿):
import?java.util.concurrent.ExecutorService;
import?java.util.concurrent.Executors;
import?java.util.concurrent.atomic.AtomicLong;
/**
*?Java線程:新特征-原子量
*
*?@author?leizhimin?2009-11-6?9:53:11
*/
public
class?Test?{
public?static?void?main(String[]?args)?{
ExecutorService?pool?=?Executors.newFixedThreadPool(2);
Runnable?t1?=?new?MyRunnable("張三",?2000);
Runnable?t2?=?new?MyRunnable("李四",?3600);
Runnable?t3?=?new?MyRunnable("王五",?2700);
Runnable?t4?=?new?MyRunnable("老張",?600);
Runnable?t5?=?new?MyRunnable("老牛",?1300);
Runnable?t6?=?new?MyRunnable("胖子",?800);
//執行各個線程
pool.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.execute(t5);
pool.execute(t6);
//關閉線程池
pool.shutdown();
}
}
class?MyRunnable?implements?Runnable?{
private?static?AtomicLong?aLong?=?new?AtomicLong(10000);??????//原子量,每個線程都可以自由操作
private?String?name;????????????????//操作人
private?int?x;????????????????????????????//操作數額
MyRunnable(String?name,?int?x)?{
this.name?=?name;
this.x?=?x;
}
public?void?run()?{
System.out.println(name?+?"執行了"?+?x?+?",當前余額:"?+?aLong.addAndGet(x));
}
}
運行結果:
李四執行了3600,當前余額:13600
王五執行了2700,當前余額:16300
老張執行了600,當前余額:16900
老牛執行了1300,當前余額:18200
胖子執行了800,當前余額:19000
張三執行了2000,當前余額:21000
Process finished with exit code 0
張三執行了2000,當前余額:12000
王五執行了2700,當前余額:18300
老張執行了600,當前余額:18900
老牛執行了1300,當前余額:20200
胖子執行了800,當前余額:21000
李四執行了3600,當前余額:15600
Process finished with exit code 0
張三執行了2000,當前余額:12000
李四執行了3600,當前余額:15600
老張執行了600,當前余額:18900
老牛執行了1300,當前余額:20200
胖子執行了800,當前余額:21000
王五執行了2700,當前余額:18300
Process finished with exit code 0
從運行結果可以看出,雖然使用了原子量,但是程序并發訪問還是有問題,那究竟問題出在哪里了?
這里要注意的一點是,原子量雖然可以保證單個變量在某一個操作過程的安全,但無法保證你整個代碼塊,或者整個程序的安全性。因此,通常還應該使用鎖等同步機制來控制整個程序的安全性。
下面是對這個錯誤修正:
import?java.util.concurrent.ExecutorService;
import?java.util.concurrent.Executors;
import?java.util.concurrent.locks.Lock;
import?java.util.concurrent.locks.ReentrantLock;
import?java.util.concurrent.atomic.AtomicLong;
/**
*?Java線程:新特征-原子量
*
*?@author?leizhimin?2009-11-6?9:53:11
*/
public?class?Test?{
public?static?void?main(String[]?args)?{
ExecutorService?pool?=?Executors.newFixedThreadPool(2);
Lock?lock?=?new?ReentrantLock(false);
Runnable?t1?=?new?MyRunnable("張三",?2000,lock);
Runnable?t2?=?new?MyRunnable("李四",?3600,lock);
Runnable?t3?=?new?MyRunnable("王五",?2700,lock);
Runnable?t4?=?new?MyRunnable("老張",?600,lock);
Runnable?t5?=?new?MyRunnable("老牛",?1300,lock);
Runnable?t6?=?new?MyRunnable("胖子",?800,lock);
//執行各個線程
pool.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.execute(t5);
pool.execute(t6);
//關閉線程池
pool.shutdown();
}
}
class?MyRunnable?implements?Runnable?{
private?static?AtomicLong?aLong?=?new?AtomicLong(10000);?????//原子量,每個線程都可以由操作
private?String?name;????????????????//操作人
private?int?x;?????????????????????//操作數額
private?Lock?lock;
MyRunnable(String?name,?int?x,Lock?lock)?{
this.name?=?name;
this.x?=?x;
this.lock?=?lock;
}
public?void?run()?{
lock.lock();
System.out.println(name?+?"執行了"?+?x?+?",當前余額:"?+?aLong.addAndGet(x));
lock.unlock();
}
}
執行結果:
張三執行了2000,當前余額:12000
王五執行了2700,當前余額:14700
老張執行了600,當前余額:15300
老牛執行了1300,當前余額:16600
胖子執行了800,當前余額:17400
李四執行了3600,當前余額:21000
Process?finished?with?exit?code?0
這里使用了一個對象鎖,來控制對并發代碼的訪問。不管運行多少次,執行次序如何,最終余額均為21000,這個結果是正確的。 有關原子量的用法很簡單,關鍵是對原子量的認識。原子量操作的是原子性的,但整個程序不線程安全的
總結
以上是生活随笔為你收集整理的java 原子量_Java原子量 - Rickxue的个人空间 - OSCHINA - 中文开源技术交流社区的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2022-2028年中国房车旅游行业深度
- 下一篇: 2022-2028年中国在线旅行预订市场