同步方法 sleep和wait 线程同步的方法
當一個線程進入一個對象的一個synchronized方法后,其它線程是否可進入此對象的其它方法?
分兩種情況
? ? ? ? ?1):進入此對象的非同步方法
? ? ? ? ? ? ? 答案:可以
? ? ? ? ?2):進入此對象的同步方法
? ? ? ? ? ? ?答案:不可以
sleep指線程被調用時,占著CPU不工作,形象地說明為“占著CPU睡覺”,此時,系統的CPU部分資源被占用,其他線程無法進入,會增加時間限制。wait指線程處于進入等待狀態,形象地說明為“等待使用CPU”,此時線程不占用任何資源,不增加時間限制。
所以
sleep(100L)意思為:占用CPU,線程休眠100毫秒
wait(100L)意思為:不占用CPU,線程等待100毫秒
JAVA中線程同步的方法(7種)匯總
同步的方法:
一、同步方法
即有synchronized關鍵字修飾的方法。?由于java的每個對象都有一個內置鎖,當用此關鍵字修飾方法時,?內置鎖會保護整個方法。在調用該方法前,需要獲得內置鎖,否則就處于阻塞狀態。 注: synchronized關鍵字也可以修飾靜態方法,此時如果調用該靜態方法,將會鎖住整個類。?
二、同步代碼塊
即有synchronized關鍵字修飾的語句塊。?被該關鍵字修飾的語句塊會自動被加上內置鎖,從而實現同步 代碼如:? synchronized(object){ } 注:同步是一種高開銷的操作,因此應該盡量減少同步的內容。通常沒有必要同步整個方法,使用synchronized代碼塊同步關鍵代碼即可。? package com.xhj.thread;/*** 線程同步的運用* * @author XIEHEJUN* */public class SynchronizedThread {class Bank {private int account = 100;public int getAccount() {return account;}/*** 用同步方法實現* * @param money*/public synchronized void save(int money) {account += money;}/*** 用同步代碼塊實現* * @param money*/public void save1(int money) {synchronized (this) {account += money;}}}三、wait與notify
wait():使一個線程處于等待狀態,并且釋放所持有的對象的lock。
sleep():使一個正在運行的線程處于睡眠狀態,是一個靜態方法,調用此方法要捕捉InterruptedException異常。
notify():喚醒一個處于等待狀態的線程,注意的是在調用此方法的時候,并不能確切的喚醒某一個等待狀態的線程,而是由JVM確定喚醒哪個線程,而且不是按優先級。
Allnotity():喚醒所有處入等待狀態的線程,注意并不是給所有喚醒線程一個對象的鎖,而是讓它們競爭。
四、使用特殊域變量(volatile)實現線程同步
a.volatile關鍵字為域變量的訪問提供了一種免鎖機制 b.使用volatile修飾域相當于告訴虛擬機該域可能會被其他線程更新 c.因此每次使用該域就要重新計算,而不是使用寄存器中的值? d.volatile不會提供任何原子操作,它也不能用來修飾final類型的變量? 例如:? 在上面的例子當中,只需在account前面加上volatile修飾,即可實現線程同步。? 代碼實例:? //只給出要修改的代碼,其余代碼與上同class Bank {//需要同步的變量加上volatileprivate volatile int account = 100;public int getAccount() {return account;}//這里不再需要synchronized public void save(int money) {account += money;}}五、使用重入鎖實現線程同步
在JavaSE5.0中新增了一個java.util.concurrent包來支持同步。? ReentrantLock類是可重入、互斥、實現了Lock接口的鎖,它與使用synchronized方法和快具有相同的基本行為和語義,并且擴展了其能力。 ReenreantLock類的常用方法有: ReentrantLock() : 創建一個ReentrantLock實例 lock() : 獲得鎖 unlock() : 釋放鎖 注:ReentrantLock()還有一個可以創建公平鎖的構造方法,但由于能大幅度降低程序運行效率,不推薦使用? 例如:? 在上面例子的基礎上,改寫后的代碼為:? //只給出要修改的代碼,其余代碼與上同class Bank {private int account = 100;//需要聲明這個鎖private Lock lock = new ReentrantLock();public int getAccount() {return account;}//這里不再需要synchronized public void save(int money) {lock.lock();try{account += money;}finally{lock.unlock();}}} ?注:關于Lock對象和synchronized關鍵字的選擇:? a.最好兩個都不用,使用一種java.util.concurrent包提供的機制,能夠幫助用戶處理所有與鎖相關的代碼。? b.如果synchronized關鍵字能滿足用戶的需求,就用synchronized,因為它能簡化代碼? c.如果需要更高級的功能,就用ReentrantLock類,此時要注意及時釋放鎖,否則會出現死鎖,通常在finally代碼釋放鎖?7.使用原子變量實現線程同步
?
需要使用線程同步的根本原因在于對普通變量的操作不是原子的。
那么什么是原子操作呢?原子操作就是指將讀取變量值、修改變量值、保存變量值看成一個整體來操作即-這幾種行為要么同時完成,要么都不完成。在java的util.concurrent.atomic包中提供了創建了原子類型變量的工具類,使用該類可以簡化線程同步。其中AtomicInteger?表可以用原子方式更新int的值,可用在應用程序中(如以原子方式增加的計數器),但不能用于替換Integer;可擴展Number,允許那些處理機遇數字類的工具和實用工具進行統一訪問。
AtomicInteger類常用方法:
AtomicInteger(int initialValue) : 創建具有給定初始值的新的
AtomicIntegeraddAddGet(int dalta) : 以原子方式將給定值與當前值相加
get() : 獲取當前值
代碼實例:
只改Bank類,其余代碼與上面第一個例子同
class Bank {private AtomicInteger account = new AtomicInteger(100);public AtomicInteger getAccount() {return account; } public void save(int money) {account.addAndGet(money);} }轉載于:https://www.cnblogs.com/jianxin-lilang/p/6445631.html
總結
以上是生活随笔為你收集整理的同步方法 sleep和wait 线程同步的方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在Ubuntu 14.04 TLS下op
- 下一篇: [codevs3044][POJ1151