- 相關(guān)推薦
Java線(xiàn)程同步的方法
線(xiàn)程的同步是Java多線(xiàn)程編程的難點(diǎn),往往開(kāi)發(fā)者搞不清楚什么是競爭資源、什么時(shí)候需要考慮同步,怎么同步等等問(wèn)題,當然,這些問(wèn)題沒(méi)有很明確的答案,但有些原則問(wèn)題需要考慮,是否有競爭資源被同時(shí)改動(dòng)的問(wèn)題?
對于同步,在具體的Java代碼中需要完成一下兩個(gè)操作:把競爭訪(fǎng)問(wèn)的資源標識為private;同步哪些修改變量的代碼,使用synchronized關(guān)鍵字同步方法或代碼。當然這不是唯一控制并發(fā)安全的途徑。synchronized關(guān)鍵字使用說(shuō)明synchronized只能標記非抽象的方法,不能標識成員變量。為了演示同步方法的使用,構建了一個(gè)信用卡賬戶(hù),起初信用額為100w,然后模擬透支、存款等多個(gè)操作。顯然銀行賬戶(hù)User對象是個(gè)競爭資源,而多個(gè)并發(fā)操作的是賬戶(hù)方法oper(int x),當然應該在此方法上加上同步,并將賬戶(hù)的余額設為私有變量,禁止直接訪(fǎng)問(wèn)。
/**
* Java線(xiàn)程:線(xiàn)程的同步
*
* @author leizhimin 2009-11-4 11:23:32
*/
public class Test {
public static void main(String[] args) {
User u = new User(“張三”, 100);
MyThread t1 = new MyThread(“線(xiàn)程A”, u, 20);
MyThread t2 = new MyThread(“線(xiàn)程B”, u, -60);
MyThread t3 = new MyThread(“線(xiàn)程C”, u, -80);
MyThread t4 = new MyThread(“線(xiàn)程D”, u, -30);
MyThread t5 = new MyThread(“線(xiàn)程E”, u, 32);
MyThread t6 = new MyThread(“線(xiàn)程F”, u, 21);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
}
}
class MyThread extends Thread {
private User u;
private int y = 0;
MyThread(String name, User u, int y) {
super(name);
this.u = u;
this.y = y;
}
public void run() {
u.oper(y);
}
}
class User {
private String code;
private int cash;
User(String code, int cash) {
this.code = code;
this.cash = cash;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
/**
* 業(yè)務(wù)方法
* @param x 添加x萬(wàn)元
*/
public synchronized void oper(int x) {
try {
Thread.sleep(10L);
this.cash += x;
System.out.println(Thread.currentThread()。getName() + “運行結束,增加” + x + “”,“當前用戶(hù)賬戶(hù)余額為:” + cash);
Thread.sleep(10L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public String toString() {
return “User{” + “code=‘” + code + ’\‘’ + “, cash=” + cash +‘}’;
}
}
輸出結果:線(xiàn)程A運行結束,增加“20”,當前用戶(hù)賬戶(hù)余額為:120.
線(xiàn)程F運行結束,增加“21”,當前用戶(hù)賬戶(hù)余額為:141.
線(xiàn)程E運行結束,增加“32”,當前用戶(hù)賬戶(hù)余額為:173.
線(xiàn)程C運行結束,增加“-80”,當前用戶(hù)賬戶(hù)余額為:93.
線(xiàn)程B運行結束,增加“-60”,當前用戶(hù)賬戶(hù)余額為:33.
線(xiàn)程D運行結束,增加“-30”,當前用戶(hù)賬戶(hù)余額為:3.
Process finished with exit code 0反面教材,不同步的情況,也就是去掉oper(int x)方法的synchronized修飾符,然后運行程序,結果如下:線(xiàn)程A運行結束,增加“20”,當前用戶(hù)賬戶(hù)余額為:61.
線(xiàn)程D運行結束,增加“-30”,當前用戶(hù)賬戶(hù)余額為:63.
線(xiàn)程B運行結束,增加“-60”,當前用戶(hù)賬戶(hù)余額為:3.
線(xiàn)程F運行結束,增加“21”,當前用戶(hù)賬戶(hù)余額為:61.
線(xiàn)程E運行結束,增加“32”,當前用戶(hù)賬戶(hù)余額為:93.
線(xiàn)程C運行結束,增加“-80”,當前用戶(hù)賬戶(hù)余額為:61.
Process finished with exit code 0很顯然,上面的結果是錯誤的,導致錯誤的原因是多個(gè)線(xiàn)程并發(fā)訪(fǎng)問(wèn)了競爭資源u,并對u的屬性做了改動(dòng)?梢(jiàn)同步的重要性。注意:通過(guò)前文可知,線(xiàn)程退出同步方法時(shí)將釋放掉方法所屬對象的鎖,但還應該注意的是,同步方法中還可以使用特定的方法對線(xiàn)程進(jìn)行調度。這些方法來(lái)自于java.lang.Object類(lèi),void notify()。
喚醒在此對象監視器上等待的單個(gè)線(xiàn)程。
void notifyAll()
喚醒在此對象監視器上等待的所有線(xiàn)程。
void wait()
導致當前的線(xiàn)程等待,直到其他線(xiàn)程調用此對象的 notify() 方法或 notifyAll() 方法。
void wait(long timeout)
導致當前的線(xiàn)程等待,直到其他線(xiàn)程調用此對象的 notify() 方法或 notifyAll() 方法,或者超過(guò)指定的時(shí)間量。
void wait(long timeout, int nanos)
導致當前的線(xiàn)程等待,直到其他線(xiàn)程調用此對象的 notify() 方法或 notifyAll() 方法,或者其他某個(gè)線(xiàn)程中斷當前線(xiàn)程,或者已超過(guò)某個(gè)實(shí)際時(shí)間量。
【Java線(xiàn)程同步的方法】相關(guān)文章:
Java枚舉的常用方法03-16
JAVA認證開(kāi)源技術(shù):關(guān)于Java的對象equals方法03-04
Java中日期的處理方法03-09
sun認證考試經(jīng)驗:多線(xiàn)程的幾種實(shí)現方法詳解01-22
Java數組操作方法大全03-04