二級(jí)Java考試輔導(dǎo)教程:6.2多線程的互斥與同步[2]

字號(hào):

synchronized 除了象上面講的放在對(duì)象前面限制一段代碼的執(zhí)行外,還可以放在方法聲明中,表示整個(gè)方法為同步方法。
    public synchronized void push(char c){
    …
     }
    如果synchronized用在類聲明中,則表明該類中的所有方法都是synchronized的。
    6.2.2多線程的同步
     本節(jié)將討論如何控制互相交互的線程之間的運(yùn)行進(jìn)度,即多線程之間的同步問(wèn)題,下面我們將通過(guò)多線程同步的模型: 生產(chǎn)者-消費(fèi)者問(wèn)題來(lái)說(shuō)明怎樣實(shí)現(xiàn)多線程的同步。
    我們把系統(tǒng)中使用某類資源的線程稱為消費(fèi)者,產(chǎn)生或釋放同類資源的線程稱為生產(chǎn)者。
    在下面的Java的應(yīng)用程序中,生產(chǎn)者線程向文件中寫數(shù)據(jù),消費(fèi)者從文件中讀數(shù)據(jù),這樣,在這個(gè)程序中同時(shí)運(yùn)行的兩個(gè)線程共享同一個(gè)文件資源。通過(guò)這個(gè)例子我們來(lái)了解怎樣使它們同步。
    類Producer是生產(chǎn)者模型,其中的 run()方法中定義了生產(chǎn)者線程所做的操作,循環(huán)調(diào)用push()方法,將生產(chǎn)的20個(gè)字母送入堆棧中,每次執(zhí)行完push操作后,調(diào)用sleep()方法睡眠一段隨機(jī)時(shí)間,以給其他線程執(zhí)行的機(jī)會(huì)。類Consumer是消費(fèi)者模型,循環(huán)調(diào)用pop()方法,從堆棧中取出一個(gè)數(shù)據(jù),一共取20次,每次執(zhí)行完pop操作后,調(diào)用sleep()方法睡眠一段隨機(jī)時(shí)間,以給其他線程執(zhí)行的機(jī)會(huì)。
    程序執(zhí)行結(jié)果
       Produced:V
       Consumed:V
       Produced:E
       Consumed:E
       Produced:P
       Produced:L
       ...
       Consumed:L
       Consumed:P
    在上述的例子中,通過(guò)運(yùn)用wait()和notify()方法來(lái)實(shí)現(xiàn)線程的同步,在同步中還會(huì)用到notifyAll()方法,一般來(lái)說(shuō),每個(gè)共享對(duì)象的互斥鎖存在兩個(gè)隊(duì)列,一個(gè)是鎖等待隊(duì)列,另一個(gè)是鎖申請(qǐng)隊(duì)列,鎖申請(qǐng)隊(duì)列中的第一個(gè)線程可以對(duì)該共享對(duì)象進(jìn)行操作,而鎖等待隊(duì)列中的線程在某些情況下將移入到鎖申請(qǐng)隊(duì)列。下面比較一下wait()、notify()和notifyAll()方法:
    (1) wait,nofity,notifyAll必須在已經(jīng)持有鎖的情況下執(zhí)行,所以它們只能出現(xiàn)在synchronized作用的范圍內(nèi),也就是出現(xiàn)在用       synchronized修飾的方法或類中。
    (2) wait的作用:釋放已持有的鎖,進(jìn)入等待隊(duì)列. 來(lái)源:www.examda.com
    (3) notify的作用:喚醒wait隊(duì)列中的第一個(gè)線程并把它移入鎖申請(qǐng)隊(duì)列.
    (4) notifyAll的作用:喚醒wait隊(duì)列中的所有的線程并把它們移入鎖申請(qǐng)隊(duì)列.
    注意:
    1) suspend()和resume()
     在JDK1.2中不再使用suspend()和resume(),其相應(yīng)功能由wait()和notify()來(lái)實(shí)現(xiàn)。
    2) stop()
     在JDK1.2中不再使用stop(),而是通過(guò)標(biāo)志位來(lái)使程序正常執(zhí)行完畢。