中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么在Java中利用多線程模擬站點售票

發布時間:2021-05-24 15:34:57 來源:億速云 閱讀:130 作者:Leah 欄目:開發技術

怎么在Java中利用多線程模擬站點售票?針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

一、實驗題目

怎么在Java中利用多線程模擬站點售票

二、分析

哦吼,這次的實驗題目是一道非常經典的多線程買票問題。題目要求我們創建5個線程來模擬賣票,當然這其中就包含多線程存在也就是我們要解決的問題,重復賣票和超額賣票。即多個窗口賣出同一張票以及窗口賣出非正數編號的票。

不過這個問題可以先放一下,我們先來創建基礎的線程模型,并在主方法中創建五個線程讓他們跑起來;

話不多說,上代碼。

public class Ticket {

	public static void main(String[] args) {
		
		for(int i = 1;i <= 5;i++) {
			//創建5個線程并啟動他們
			//注意一定要使用Thread類創建線程并使用start方法啟動
			//而不是直接創建TicketSeller對象調用run方法!!!!!!
			new Thread(new TicketSeller(i)).start();
		}
	}
}

//售票類,實現Runnable接口,可以作為線程執行對象
class TicketSeller implements Runnable{

	//該售票窗口編號
	private int code;
	
	public TicketSeller(int code) {
		this.code = code;
	}
	
	@Override
	public void run() {
		for(int i = 0;i < 5;i++) {
			System.out.println(code + "號窗口");
			
			//為了使線程能夠交替執行,打印完成語句讓線程休眠一小會
			try {
				Thread.sleep(300);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

代碼的含義和需要注意的點都在注釋里面了,一定要看注釋!!!

運行結果就是:

怎么在Java中利用多線程模擬站點售票

后面太長了就不放了。。。。

完成了基礎的多線程框架搭建后,我們來為每個線程執行過程中加入賣票的程序

首先要解決的一個問題是:票存在哪里?。毋庸置疑的是由于是多線程并發的售票,因此票這個變量一定是被多個線程所共享的,而不能是每個線程對象自己的屬性。

一個可行的方案是在TicketSellet類中定義靜態的票計數,這樣所有的線程訪問票的時候訪問的都是同一個票計數變量。

另一個可行方案是使用一個對象管理票,票計數是這個對象的成員,并且讓每個TicketSeller持有相同的對象。那么多個線程也同樣共享票計數。

當然,可行的方案還有很多,現在我們先來實現第一種,在之后的改進中,我們還會用到第二種。

先來一個沒有加鎖的寫法,看看他的問題

//售票類,實現Runnable接口,可以作為線程執行對象
class TicketSeller implements Runnable{

	//票數
	private static int tickets = 100;
	
	//該售票窗口編號
	private int code;
	
	public TicketSeller(int code) {
		this.code = code;
	}
	
	@Override
	public void run() {
			
		//如果有票就一直賣
		while(tickets > 0) {
			System.out.println(code + "_____" + tickets--);
			
			//賣過票之后休眠一小會等待其他線程操作
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
			
	}
	
}

這段不加鎖的代碼會遇到許多很尷尬的問題,首先一個,多線程之間的重復賣票:

怎么在Java中利用多線程模擬站點售票

除了重復賣票,還有超額賣票的行為:

怎么在Java中利用多線程模擬站點售票

這當然是不能容忍的,解決辦法是在賣票過程對tickets變量加鎖,使得每次只能有一個線程進入賣票的環節而其他線程只能循環等待:

怎么在Java中利用多線程模擬站點售票

怎么在Java中利用多線程模擬站點售票

但是這樣處理并不能完全結局上面的問題,盡管每次只能一個線程進入賣票階段阻止了重復賣票。但是超額賣票的行為依舊會發生:

怎么在Java中利用多線程模擬站點售票

好嘛,這次非常嚴重

原因嗎其實并不復雜,我們加鎖只是能阻止多個進程進入賣票程序,但是會有其他程序達成判斷條件,執行到賣票程序之前等待進入,如果一個線程將票賣完而此時有其他程序剛好等待進入,那么就會出現上面的情況。

所以我們還需要加上一道保險:

怎么在Java中利用多線程模擬站點售票

經過這樣的處理,票子就可以放心的賣出而不用擔心重或者賣超了

三、完整代碼:

public class Ticket {

	public static void main(String[] args) {
		
		for(int i = 1;i <= 5;i++) {
			//創建5個線程并啟動他們
			//注意一定要使用Thread類創建線程并使用start方法啟動
			//而不是直接創建TicketSeller對象調用run方法!!!!!!
			new Thread(new TicketSeller(i)).start();
		}
	}
}

//售票類,實現Runnable接口,可以作為線程執行對象
class TicketSeller implements Runnable{

	//票數
	private static int tickets = 100;

	//同步鎖
	private static Object lock = new Object();
	
	//該售票窗口編號
	private int code;
	
	public TicketSeller(int code) {
		this.code = code;
	}
	
	@Override
	public void run() {
			
		//如果有票就一直賣
		while(tickets > 0) {
			synchronized (lock) {
				
				//如果票賣完了則跳出
				if(tickets <= 0) {
					break;
				}
				
				System.out.println(code + "_____" + tickets--);
				
				//賣過票之后休眠一小會等待其他線程操作
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
			
	}
	
}

在前面我們還提出了另一種方案,就是使用一個對象管理票的售賣。這種方案就不展開啰嗦了,直接上代碼:

public class Ticket {

	public static void main(String[] args) {
		//創建一個票管理對象,票數為100
		TicketSet ts = new TicketSet(100);
	
		//創建5個線程,使用同一個票管理對象
		for(int i = 1;i <= 5;i++) {
			new Thread(new TicketSeller(ts, i)).start();
		}
	}
}

//票管理類
class TicketSet{
	
	//票數
	private int tickets;
	
	public TicketSet(int tickets) {
		this.tickets = tickets;
	}
	
	
	private boolean hasTicket() {
		return tickets > 0;
	}
	
	//售票方法,使用同步鎖,每次只能有一個線程訪問該方法
	//返回結果為是否賣出去票
	synchronized public boolean sellTicket(int code) {
		if(hasTicket()) {
			System.out.println(code + "_____" + tickets--);
			return true;
		}else {
			return false;
		}
	}
}

//售票類
class TicketSeller implements Runnable{
	//票管理對象
	private TicketSet ts;

	private int code;
	
	public TicketSeller(TicketSet ts,int code) {
		this.ts = ts;
		this.code = code;
	}

	@Override
	public void run() {
		//嘗試調用票管理的售票方法,售票成功后休眠一小會
		while(ts.sellTicket(code)){
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

java基本數據類型有哪些

Java的基本數據類型分為:1、整數類型,用來表示整數的數據類型。2、浮點類型,用來表示小數的數據類型。3、字符類型,字符類型的關鍵字是“char”。4、布爾類型,是表示邏輯值的基本數據類型。

關于怎么在Java中利用多線程模擬站點售票問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

历史| 滁州市| 台南县| 广州市| 资溪县| 克山县| 景宁| 惠水县| 绥阳县| 丰县| 高台县| 新干县| 马公市| 柘城县| 双柏县| 交城县| 肥东县| 天柱县| 迭部县| 镇沅| 辽中县| 新乡县| 綦江县| 雅江县| 株洲市| 浏阳市| 阜宁县| 安丘市| 五华县| 云霄县| 宁德市| 开原市| 伽师县| 义马市| 安泽县| 南岸区| 洪泽县| 申扎县| 松阳县| 紫金县| 蒙自县|