基本线程同步(三)在同步的类里安排独立属性
聲明:本文是《?Java 7 Concurrency Cookbook?》的第二章,作者: Javier Fernández González ? ? 譯者:許巧輝 ?校對:方騰飛
在同步的類里安排獨立屬性
當你使用synchronized關鍵字來保護代碼塊時,你必須通過一個對象的引用作為參數。通常,你將會使用this關鍵字來引用執行該方法的對象,但是你也可以使用其他對象引用。通常情況下,這些對象被創建只有這個目的。比如,你在一個類中有被多個線程共享的兩個獨立屬性。你必須同步訪問每個變量,如果有一個線程訪問一個屬性和另一個線程在同一時刻訪問另一個屬性,這是沒有問題的。
在這個指南中,你將學習如何解決這種情況的一個例子,編程模擬一家電影院有兩個屏幕和兩個售票處。當一個售票處出售門票,它們用于兩個電影院的其中一個,但不能用于兩個,所以在每個電影院的免費席位的數量是獨立的屬性。
準備工作
這個指南的例子使用Eclipse IDE實現。如果你使用Eclipse或其他IDE,如NetBeans,打開它并創建一個新的Java項目。
如何做…
按以下步驟來實現的這個例子:
1.創建一個Cinema類,添加兩個long類型的屬性,命名為vacanciesCinema1和vacanciesCinema2。
public class Cinema { private long vacanciesCinema1; private long vacanciesCinema2;2.給Cinema類添加兩個額外的Object屬性,命名為controlCinema1和controlCinema2。
private final Object controlCinema1, controlCinema2;3.實現Cinema類的構造方法,初始化所有屬性。
public Cinema(){ controlCinema1=new Object(); controlCinema2=new Object(); vacanciesCinema1=20; vacanciesCinema2=20; }4.實現sellTickets1()方法,當第一個電影院出售一些門票將調用它。使用controlCinema1對象來控制訪問synchronized的代碼塊。
public boolean sellTickets1 (int number) { synchronized (controlCinema1) { if (number<vacanciesCinema1) { vacanciesCinema1-=number; return true; } else { return false; } } }5.實現sellTickets2()方法,當第二個電影院出售一些門票將調用它。使用controlCinema2對象來控制訪問synchronized的代碼塊。
public boolean sellTickets2 (int number) { synchronized (controlCinema2) { if (number<vacanciesCinema2) { vacanciesCinema2-=number; return true; } else { return false; } } }6.實現returnTickets1()方法,當第一個電影院被退回一些票時將調用它。使用controlCinema1對象來控制訪問synchronized的代碼塊。
public boolean returnTickets1 (int number) { synchronized (controlCinema1) { vacanciesCinema1+=number; return true; } }7.實現returnTickets2()方法,當第二個電影院被退回一些票時將調用它。使用controlCinema2對象來控制訪問synchronized的代碼塊。
public boolean returnTickets2 (int number) { synchronized (controlCinema2) { vacanciesCinema2+=number; return true; } }8.實現其他兩個方法,用來返回每個電影院空缺位置的數量。
public long getVacanciesCinema1() { return vacanciesCinema1; } public long getVacanciesCinema2() { return vacanciesCinema2; }9.實現TicketOffice1類,并指定它實現Runnable接口。
public class TicketOffice1 implements Runnable {10.聲明一個Cinema對象,并實現該類(類TicketOffice1)的構造器用來初始化這個對象。
private Cinema cinema; public TicketOffice1 (Cinema cinema) { this.cinema=cinema; }11.實現run()方法,用來模擬在兩個電影院的一些操作。
@Override public void run() { cinema.sellTickets1(3); cinema.sellTickets1(2); cinema.sellTickets2(2); cinema.returnTickets1(3); cinema.sellTickets1(5); cinema.sellTickets2(2); cinema.sellTickets2(2); cinema.sellTickets2(2); }12.實現TicketOffice2類,并指定它實現Runnable接口。
public class TicketOffice2 implements Runnable {13.聲明一個Cinema對象,并實現該類(類TicketOffice2)的構造器用來初始化這個對象。
private Cinema cinema; public TicketOffice2 (Cinema cinema) { this.cinema=cinema; }14.實現run()方法,用來模擬在兩個電影院的一些操作。
@Override public void run() { cinema.sellTickets2(2); cinema.sellTickets2(4); cinema.sellTickets1(2); cinema.sellTickets1(1); cinema.returnTickets2(2); cinema.sellTickets1(3); cinema.sellTickets2(2); cinema.sellTickets1(2); }15.通過創建類名為Main,且包括main()方法來實現這個示例的主類。
public class Main { public static void main(String[] args) {16.聲明和創建一個Cinema對象。
Cinema cinema=new Cinema();17.創建一個TicketOffice1對象,并且用線程來運行它。
TicketOffice1 ticketOffice1=new TicketOffice1(cinema); Thread thread1=new Thread(ticketOffice1,"TicketOffice1");18.創建一個TicketOffice2對象,并且用線程來運行它。
TicketOffice2 ticketOffice2=new TicketOffice2(cinema); Thread thread2=new Thread(ticketOffice2,"TicketOffice2");19.啟動這兩個線程。
thread1.start(); thread2.start();20.等待線程執行完成。
try { thread1.join(); thread2.join(); } catch (InterruptedException e) { e.printStackTrace(); }21.兩個電影院的空缺數寫入控制臺。
System.out.printf("Room 1 Vacancies: %d\n",cinema.getVacanciesCinema1()); System.out.printf("Room 2 Vacancies: %d\n",cinema.getVacanciesCinema2());它是如何工作的…
當你使用synchronized關鍵字來保護代碼塊,你使用一個對象作為參數。JVM可以保證只有一個線程可以訪問那個對象保護所有的代碼塊(請注意,我們總是談論的對象,而不是類)。
注釋:在這個示例中,我們用一個對象來控制vacanciesCinema1屬性的訪問。所以,在任意時刻,只有一個線程能修改該屬性。用另一個對象來控制 vacanciesCinema2屬性的訪問。所以,在任意時刻,只有一個線程能修改這個屬性。但是可能有兩個線程同時運行,一個修改 vacancesCinema1屬性而另一個修改vacanciesCinema2屬性。
當你運行這個示例,你可以看到每個電影院的空缺數量的最后的結果總是預期的。在以下截圖中,你可以看到應用程序的執行結果:
不止這些…
synchronize關鍵字還有其他重要用法,請見其他指南中解釋這個關鍵字使用的參見部分。
參見
在第2章,基本線程同步中在同步代碼中使用條件的指南。
文章轉自?并發編程網-ifeve.com
總結
以上是生活随笔為你收集整理的基本线程同步(三)在同步的类里安排独立属性的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在P2P市场中代替“看不见的手”的算法在
- 下一篇: 《计算机组成原理》----2.3 二进