王艳 201771010127《面向对象程序设计(java)》第十七周学习总结
實(shí)驗(yàn)十七 ?線程同步控制
實(shí)驗(yàn)時(shí)間 2018-12-10
一、理論部分
1.線程同步:多線程并發(fā)運(yùn)行不確定性問題解決方案:引入線程同步機(jī)制,使得另一線程要使用該方法,就只能等待。
解決方案:
1)鎖對(duì)象與條件對(duì)象
有關(guān)鎖對(duì)象和條件對(duì)象的關(guān)鍵要點(diǎn):
? 鎖用來保護(hù)代碼片段,保證任何時(shí)刻只能有一個(gè)線程執(zhí)行被保護(hù)的代碼。
? 鎖管理試圖進(jìn)入被保護(hù)代碼段的線程。
? 鎖可擁有一個(gè)或多個(gè)相關(guān)條件對(duì)象。
? 每個(gè)條件對(duì)象管理那些已經(jīng)進(jìn)入被保護(hù)的代碼段但還不能運(yùn)行的線程。
2)synchronized關(guān)鍵字
某個(gè)類內(nèi)方法用synchronized 修飾后,該方法被稱為同步方法;
只要某個(gè)線程正在訪問同步方法,其他線程欲要訪問同步方法就被阻塞,直至線程從同步方法返回前喚醒被阻塞線程,其他線程方可能進(jìn)入同步方法。
一個(gè)線程在使用的同步方法中時(shí),可能根據(jù)問題的需要,必須使用wait()方法使本線程等待,暫時(shí)讓出CPU的使用權(quán),并允許其它線程使用這個(gè)同步方法。
線程如果用完同步方法,應(yīng)當(dāng)執(zhí)行notifyAll()方法通知所有由于使用這個(gè)同步方法而處于等待的線程結(jié)束等待。
二、實(shí)驗(yàn)部分
1、實(shí)驗(yàn)?zāi)康呐c要求
(1) 掌握線程同步的概念及實(shí)現(xiàn)技術(shù);
(2) 線程綜合編程練習(xí)
2、實(shí)驗(yàn)內(nèi)容和步驟
實(shí)驗(yàn)1:測(cè)試程序并進(jìn)行代碼注釋。
測(cè)試程序1:
l?在Elipse環(huán)境下調(diào)試教材651頁(yè)程序14-7,結(jié)合程序運(yùn)行結(jié)果理解程序;
掌握利用鎖對(duì)象和條件對(duì)象實(shí)現(xiàn)的多線程同步技術(shù)。
程序如下:
package test2;/*** This program shows how multiple threads can safely access a data structure.* @version 1.31 2015-06-21* @author Cay Horstmann*/ public class SynchBankTest {public static final int NACCOUNTS = 100;public static final double INITIAL_BALANCE = 1000;public static final double MAX_AMOUNT = 1000;public static final int DELAY = 10;public static void main(String[] args){Bank bank = new Bank(NACCOUNTS, INITIAL_BALANCE);for (int i = 0; i < NACCOUNTS; i++){int fromAccount = i;Runnable r = () -> {try{while (true){int toAccount = (int) (bank.size() * Math.random());double amount = MAX_AMOUNT * Math.random();bank.transfer(fromAccount, toAccount, amount);Thread.sleep((int) (DELAY * Math.random()));}}catch (InterruptedException e){} };Thread t = new Thread(r);t.start();}} } package test2;import java.util.*; import java.util.concurrent.locks.*;/*** A bank with a number of bank accounts that uses locks for serializing access.* @version 1.30 2004-08-01* @author Cay Horstmann*/ public class Bank {private final double[] accounts;private Lock bankLock;private Condition sufficientFunds;/*** Constructs the bank.* @param n the number of accounts* @param initialBalance the initial balance for each account*/public Bank(int n, double initialBalance){accounts = new double[n];Arrays.fill(accounts, initialBalance);bankLock = new ReentrantLock();sufficientFunds = bankLock.newCondition();}/*** Transfers money from one account to another.* @param from the account to transfer from* @param to the account to transfer to* @param amount the amount to transfer*/public void transfer(int from, int to, double amount) throws InterruptedException{bankLock.lock();try{while (accounts[from] < amount)sufficientFunds.await();System.out.print(Thread.currentThread());accounts[from] -= amount;System.out.printf(" %10.2f from %d to %d", amount, from, to);accounts[to] += amount;System.out.printf(" Total Balance: %10.2f%n", getTotalBalance());sufficientFunds.signalAll();}finally{bankLock.unlock();}}/*** Gets the sum of all account balances.* @return the total balance*/public double getTotalBalance(){bankLock.lock();try{double sum = 0;for (double a : accounts)sum += a;return sum;}finally{bankLock.unlock();}}/*** Gets the number of accounts in the bank.* @return the number of accounts*/public int size(){return accounts.length;} }程序運(yùn)行結(jié)果如下:
測(cè)試程序2:
l?在Elipse環(huán)境下調(diào)試教材655頁(yè)程序14-8,結(jié)合程序運(yùn)行結(jié)果理解程序;
l?掌握synchronized在多線程同步中的應(yīng)用。
程序如下:
?
package test2;/*** This program shows how multiple threads can safely access a data structure,* using synchronized methods.* @version 1.31 2015-06-21* @author Cay Horstmann*/ public class SynchBankTest2 {public static final int NACCOUNTS = 100;public static final double INITIAL_BALANCE = 1000;public static final double MAX_AMOUNT = 1000;public static final int DELAY = 10;public static void main(String[] args){Bank bank = new Bank(NACCOUNTS, INITIAL_BALANCE);for (int i = 0; i < NACCOUNTS; i++){int fromAccount = i;Runnable r = () -> {try{while (true){int toAccount = (int) (bank.size() * Math.random());double amount = MAX_AMOUNT * Math.random();bank.transfer(fromAccount, toAccount, amount);Thread.sleep((int) (DELAY * Math.random()));}}catch (InterruptedException e){}};Thread t = new Thread(r);t.start();}} }?
package test2;import java.util.*; import java.util.concurrent.locks.*;/*** A bank with a number of bank accounts that uses locks for serializing access.* @version 1.30 2004-08-01* @author Cay Horstmann*/ public class Bank {private final double[] accounts;private Lock bankLock;private Condition sufficientFunds;/*** Constructs the bank.* @param n the number of accounts* @param initialBalance the initial balance for each account*/public Bank(int n, double initialBalance){accounts = new double[n];Arrays.fill(accounts, initialBalance);bankLock = new ReentrantLock();sufficientFunds = bankLock.newCondition();}/*** Transfers money from one account to another.* @param from the account to transfer from* @param to the account to transfer to* @param amount the amount to transfer*/public void transfer(int from, int to, double amount) throws InterruptedException{bankLock.lock();try{while (accounts[from] < amount)sufficientFunds.await();System.out.print(Thread.currentThread());accounts[from] -= amount;System.out.printf(" %10.2f from %d to %d", amount, from, to);accounts[to] += amount;System.out.printf(" Total Balance: %10.2f%n", getTotalBalance());sufficientFunds.signalAll();}finally{bankLock.unlock();}}/*** Gets the sum of all account balances.* @return the total balance*/public double getTotalBalance(){bankLock.lock();try{double sum = 0;for (double a : accounts)sum += a;return sum;}finally{bankLock.unlock();}}/*** Gets the number of accounts in the bank.* @return the number of accounts*/public int size(){return accounts.length;} }程序運(yùn)行結(jié)果:
測(cè)試程序3:
l?在Elipse環(huán)境下運(yùn)行以下程序,結(jié)合程序運(yùn)行結(jié)果分析程序存在問題;
l?嘗試解決程序中存在問題。
package test2; class Cbank {private static int s=2000;public static void sub(int m){int temp=s;temp=temp-m;try {Thread.sleep((int)(1000*Math.random()));}catch (InterruptedException e) { }s=temp;System.out.println("s="+s);}}class Customer extends Thread {public void run(){for( int i=1; i<=4; i++)Cbank.sub(100);}} public class Thread3 {public static void main(String args[]){Customer customer1 = new Customer();Customer customer2 = new Customer();customer1.start();customer2.start();} }程序運(yùn)行后如圖:
分析程序,輸出結(jié)果應(yīng)為1900—1200,而控制臺(tái)上顯示結(jié)果有重復(fù)。因?yàn)闆]有對(duì)程序加上鎖功能。修改后程序如下:
package test2; class Cbank {private static int s=2000;public synchronized static void sub(int m){int temp=s;temp=temp-m;try {Thread.sleep((int)(1000*Math.random()));}catch (InterruptedException e) { }s=temp;System.out.println("s="+s);}}class Customer extends Thread {public void run(){for( int i=1; i<=4; i++)Cbank.sub(100);}} public class Thread3 {public static void main(String args[]){Customer customer1 = new Customer();Customer customer2 = new Customer();customer1.start();customer2.start();} }程序運(yùn)行結(jié)果如下:
實(shí)驗(yàn)2?編程練習(xí)
利用多線程及同步方法,編寫一個(gè)程序模擬火車票售票系統(tǒng),共3個(gè)窗口,賣10張票,程序輸出結(jié)果類似(程序輸出不唯一,可以是其他類似結(jié)果)。
Thread-0窗口售:第1張票
Thread-0窗口售:第2張票
Thread-1窗口售:第3張票
Thread-2窗口售:第4張票
Thread-2窗口售:第5張票
Thread-1窗口售:第6張票
Thread-0窗口售:第7張票
Thread-2窗口售:第8張票
Thread-1窗口售:第9張票
Thread-0窗口售:第10張票
程序如下:
?
package test2;public class Demo {public static void main(String[] args) {Mythread mythread = new Mythread();Thread ticket1 = new Thread(mythread);Thread ticket2 = new Thread(mythread);Thread ticket3 = new Thread(mythread);ticket1.start();ticket2.start();ticket3.start();} }class Mythread implements Runnable {int ticket = 1;boolean flag = true;@Overridepublic void run() {while (flag) {try {Thread.sleep(500);} catch (InterruptedException e) {// TODO Auto-generated catch block e.printStackTrace();}synchronized (this) {if (ticket <= 10) {System.out.println(Thread.currentThread().getName() + "窗口售:第" + ticket + "張票");ticket++;}if (ticket > 10) {flag = false;}}}}}?
程序運(yùn)行結(jié)果如下:
三:實(shí)驗(yàn)總結(jié)
? ? ? 這周繼續(xù)學(xué)習(xí)了有關(guān)線程的知識(shí),主要學(xué)習(xí)了有關(guān)線程同步的問題。線程同步主要是為了解決多線程并發(fā)運(yùn)行不確定性問題,使得多個(gè)線程中在一個(gè)線程使用某種方法時(shí)候,另一線程要使用該方法,就只能等待。實(shí)驗(yàn)課上,老師和學(xué)長(zhǎng)通過演示具體的例子給我們展現(xiàn)了多線程中在不加鎖時(shí)會(huì)出現(xiàn)的情況,讓我們對(duì)線程同步有了更加清晰地認(rèn)識(shí)。雖然很多地方還是不太懂還是存在很大的問題,但是實(shí)驗(yàn)課上講的內(nèi)容聽得比較清晰,課后自己再運(yùn)行試驗(yàn)時(shí)也有了更深的體會(huì)。
?
轉(zhuǎn)載于:https://www.cnblogs.com/JAVA-729/p/10159644.html
總結(jié)
以上是生活随笔為你收集整理的王艳 201771010127《面向对象程序设计(java)》第十七周学习总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: #Node.js的fs导入遇到的问题和解
- 下一篇: 第五章:条件、循环以及其他语句(上)