基礎回顧
1 wait方法:
該方法屬於Object的方法,wait方法的作用是使得當前呼叫wait方法所在部分(程式碼塊)的執行緒停止執行,並釋放當前獲得的呼叫wait所在的程式碼塊的鎖,並在其他執行緒呼叫notify或者notifyAll方法時恢復到競爭鎖狀態(一旦獲得鎖就恢復執行)。
呼叫wait方法需要注意幾點:
第一點:wait被呼叫的時候必須在擁有鎖(即synchronized修飾的)的程式碼塊中。
第二點:恢復執行後,從wait的下一條語句開始執行,因而wait方法總是應當在while迴圈中呼叫,以免出現恢復執行後繼續執行的條件不滿足卻繼續執行的情況。
第三點:若wait方法引數中帶時間,則除了notify和notifyAll被呼叫能啟用處於wait狀態(等待狀態)的執行緒進入鎖競爭外,在其他執行緒中interrupt它或者引數時間到了之後,該執行緒也將被啟用到競爭狀態。
第四點:wait方法被呼叫的執行緒必須獲得之前執行到wait時釋放掉的鎖重新獲得才能夠恢復執行。
2 notify方法和notifyAll方法:
notify方法通知呼叫了wait方法,但是尚未啟用的一個執行緒進入執行緒排程佇列(即進入鎖競爭),注意不是立即執行。並且具體是哪一個執行緒不能保證。另外一點就是被喚醒的這個執行緒一定是在等待wait所釋放的鎖。
notifyAll方法則喚醒所有呼叫了wait方法,尚未啟用的程式進入競爭佇列。
3 synchronized關鍵字:
第一點:synchronized用來標識一個普通方法時,表示一個執行緒要執行該方法,必須取得該方法所在的物件的鎖。
第二點:synchronized用來標識一個靜態方法時,表示一個執行緒要執行該方法,必須獲得該方法所在的類的類鎖。
第三點:synchronized修飾一個程式碼塊。類似這樣:synchronized(obj) { //co
該方法屬於Object的方法,wait方法的作用是使得當前呼叫wait方法所在部分(程式碼塊)的執行緒停止執行,並釋放當前獲得的呼叫wait所在的程式碼塊的鎖,並在其他執行緒呼叫notify或者notifyAll方法時恢復到競爭鎖狀態(一旦獲得鎖就恢復執行)。
呼叫wait方法需要注意幾點:
第一點:wait被呼叫的時候必須在擁有鎖(即synchronized修飾的)的程式碼塊中。
第二點:恢復執行後,從wait的下一條語句開始執行,因而wait方法總是應當在while迴圈中呼叫,以免出現恢復執行後繼續執行的條件不滿足卻繼續執行的情況。
第三點:若wait方法引數中帶時間,則除了notify和notifyAll被呼叫能啟用處於wait狀態(等待狀態)的執行緒進入鎖競爭外,在其他執行緒中interrupt它或者引數時間到了之後,該執行緒也將被啟用到競爭狀態。
第四點:wait方法被呼叫的執行緒必須獲得之前執行到wait時釋放掉的鎖重新獲得才能夠恢復執行。
2 notify方法和notifyAll方法:
notify方法通知呼叫了wait方法,但是尚未啟用的一個執行緒進入執行緒排程佇列(即進入鎖競爭),注意不是立即執行。並且具體是哪一個執行緒不能保證。另外一點就是被喚醒的這個執行緒一定是在等待wait所釋放的鎖。
notifyAll方法則喚醒所有呼叫了wait方法,尚未啟用的程式進入競爭佇列。
3 synchronized關鍵字:
第一點:synchronized用來標識一個普通方法時,表示一個執行緒要執行該方法,必須取得該方法所在的物件的鎖。
第二點:synchronized用來標識一個靜態方法時,表示一個執行緒要執行該方法,必須獲得該方法所在的類的類鎖。
第三點:synchronized修飾一個程式碼塊。類似這樣:synchronized(obj) { //co
de.... }。表示一個執行緒要執行該程式碼塊,必須獲得obj的鎖。這樣做的目的是減小鎖的粒度,保證當不同塊所需的鎖不衝突時不用對整個物件加鎖。利用零長度的byte陣列物件做obj非常經濟。
4 atomic action(原子操作):
在JAVA中,以下兩點操作是原子操作。但是c和c++中並不如此。
第一點:對引用變數和除了long和double之外的原始資料型別變數進行讀寫。
第二點:對所有宣告為volatile的變數(包括long和double)的讀寫。
另外:在java.util.concurrent和java.util.concurrent.atomic包中提供了一些不依賴於同步機制的執行緒安全的類和方法。
5 一個例子,該例子模仿多人存取同一個賬戶:
Account類:
package com.synchronize;
import java.util.HashMap;
import java.util.Iterator;
public class Account {
private static HashMap<String, Integer> m = new HashMap<String, Integer>();
private static long times = 0;
static {
m.put("ren", 1000);
}
public synchronized void save(String name, int num) {
long tempTime = times++;
System.out.println("第 " + tempTime + " 次儲存" + num + "之前" + name + "的餘額為:" + m.get(name));
m.put(name, m.get(name) + num);
this.notify();
System.out.println("第 " + tempTime + " 次儲存" + num + "之後" + name + "的餘額為:" + m.get(name));
}
public static int get(String name) {
return m.get(name);
}
/**
* 注意wait的用法,必須在loop中,必須在擁有鎖的程式碼塊中。 前者是當被notify的時候要重新進行條件判斷,後者是為了釋放鎖。
*
* @param name
* @param num
*/
public synchronized void load(String name, int num) {
long tempTime = times++;
System.out.println("第 " + tempTime + " 次提取" + num + "之前" + name + "的餘額為:" + m.get(name));
try {
while (m.get(name) < num) {
System.out.println("第 " + tempTime + " 次提取" + "餘額" + m.get(name) + "不足,開始等待wait。");
this.wait();
System.out.println("第 " + tempTime + " 次提取操作被喚醒");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
m.put(name, m.get(name) - num);
System.out.println("第 " + tempTime + " 次提取" + num + "之後" + name + "的餘額為:" + m.get(name));
}
}
User類:
package com.synchronize;
/**
* 這裡注意runnable介面的執行緒是怎麼例項化的。new Thread(new User())
* 這裡成功展示了多個使用者存取同一個賬戶的多執行緒例項,通過多執行緒同步,保證了安全的執行。
* @author abc
*
*/
public class User implements Runnable {
private static Account account = new Account();
private final int id;
User(int i){
id=i;
}
public void run() {
int tempMoney = 100;
account.load("ren", tempMoney);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
account.save("ren", 100);
System.out.println("執行緒"+id+"完畢========================================================");
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(new User(i)).start();
}
}
}
4 atomic action(原子操作):
在JAVA中,以下兩點操作是原子操作。但是c和c++中並不如此。
第一點:對引用變數和除了long和double之外的原始資料型別變數進行讀寫。
第二點:對所有宣告為volatile的變數(包括long和double)的讀寫。
另外:在java.util.concurrent和java.util.concurrent.atomic包中提供了一些不依賴於同步機制的執行緒安全的類和方法。
5 一個例子,該例子模仿多人存取同一個賬戶:
Account類:
package com.synchronize;
import java.util.HashMap;
import java.util.Iterator;
public class Account {
private static HashMap<String, Integer> m = new HashMap<String, Integer>();
private static long times = 0;
static {
m.put("ren", 1000);
}
public synchronized void save(String name, int num) {
long tempTime = times++;
System.out.println("第 " + tempTime + " 次儲存" + num + "之前" + name + "的餘額為:" + m.get(name));
m.put(name, m.get(name) + num);
this.notify();
System.out.println("第 " + tempTime + " 次儲存" + num + "之後" + name + "的餘額為:" + m.get(name));
}
public static int get(String name) {
return m.get(name);
}
/**
* 注意wait的用法,必須在loop中,必須在擁有鎖的程式碼塊中。 前者是當被notify的時候要重新進行條件判斷,後者是為了釋放鎖。
*
* @param name
* @param num
*/
public synchronized void load(String name, int num) {
long tempTime = times++;
System.out.println("第 " + tempTime + " 次提取" + num + "之前" + name + "的餘額為:" + m.get(name));
try {
while (m.get(name) < num) {
System.out.println("第 " + tempTime + " 次提取" + "餘額" + m.get(name) + "不足,開始等待wait。");
this.wait();
System.out.println("第 " + tempTime + " 次提取操作被喚醒");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
m.put(name, m.get(name) - num);
System.out.println("第 " + tempTime + " 次提取" + num + "之後" + name + "的餘額為:" + m.get(name));
}
}
User類:
package com.synchronize;
/**
* 這裡注意runnable介面的執行緒是怎麼例項化的。new Thread(new User())
* 這裡成功展示了多個使用者存取同一個賬戶的多執行緒例項,通過多執行緒同步,保證了安全的執行。
* @author abc
*
*/
public class User implements Runnable {
private static Account account = new Account();
private final int id;
User(int i){
id=i;
}
public void run() {
int tempMoney = 100;
account.load("ren", tempMoney);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
account.save("ren", 100);
System.out.println("執行緒"+id+"完畢========================================================");
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(new User(i)).start();
}
}
}
相關文章
- 回顧JavaScript基礎——函式JavaScript函式
- Java基礎知識回顧Java
- C#基礎委託回顧C#
- Java基礎知識回顧 -SQLJavaSQL
- day001|python基礎回顧Python
- Azure Data Factory(九)基礎知識回顧
- C#基礎回顧:正規表示式C#
- Java基礎知識回顧之六 —– IO流Java
- Android知識點回顧之Activity基礎Android
- Android知識點回顧之Service基礎Android
- Java基礎知識回顧之六 ----- IO流Java
- 前端基礎重點回顧2: HTTP協議前端HTTP協議
- C++基礎回顧4——動態陣列C++陣列
- Python回顧與整理1:Python基礎Python
- Linux 基礎回顧 之 程式與空間Linux
- Java基礎知識回顧之七 —– 總結篇Java
- Java基礎回顧(牛客網專案課程)Java
- 閱讀原始碼,通過LinkedList回顧基礎原始碼
- Java基礎知識回顧之七 ----- 總結篇Java
- mysql優化筆記--基礎知識整理回顧MySql優化筆記
- Java基礎知識回顧之五 ----- 多執行緒Java執行緒
- Linux 基礎回顧 之 檔案與許可權Linux
- C++基礎回顧4——智慧指標shared_ptrC++指標
- React基礎再回顧React
- C++基礎回顧5——類的拷貝、複製和銷燬C++
- C#基礎回顧:使用csc.exe構建C#應用程式C#
- FI顧問基礎知識
- Git指令回顧Git
- C#基礎知識回顧:1.由WeakReference想到物件的建立與銷燬C#物件
- 活動精彩回顧|GopherChina 2019乾貨回顧!Go
- js回顧:原型鏈JS原型
- PHP 回顧之 cookiePHPCookie
- 回顧 crash log 分析
- javascript知識回顧JavaScript
- flex知識回顧Flex
- 5. SQL回顧SQL
- SpringMVC 回顧servletSpringMVCServlet
- GoogleDeveloperDay 回顧GoDeveloper