Java之執行緒同步完成售票例項的6種方式

鄭清發表於2018-08-29

自定義執行緒和執行緒同步原理不懂的可以先看下面2個連結資料

Java之自定義執行緒的2種方式:https://blog.csdn.net/qq_38225558/article/details/82118862

Java之執行緒安全問題的3種處理方式(通過執行緒同步):https://blog.csdn.net/qq_38225558/article/details/82154321

 

執行緒同步:完成多執行緒售票例項   ==>  假設存在2個視窗售票

第1種方式:自定義執行緒繼承Thread類     同步方法 ==> 使用synchronized 修飾方法  

public class Demo1{
	public static void main(String[] args) {
		Station station = new Station();
		TicketThread t1 = new TicketThread(station);
		TicketThread t2 = new TicketThread(station);
		t1.start();
		t2.start();
	}
}
class Station{
	private static int tickets = 20;//記錄車票的數量   使用static目的:確保2個視窗是共同在出售這20張票而不是這2個視窗各自出售20張 共出售40張
    //定義一個買票的方法
	public synchronized void getTicket(){
		if(tickets>0){
			System.out.println("車票還剩: "+ (--tickets) + "張 !");
		}
	}
}
class TicketThread extends Thread{
	private Station station;
	public TicketThread(Station station) {
		this.station = station;
	}
	@Override
	public void run() {
		while(true){
			station.getTicket();
		}	
	}
}

執行結果圖:


第2種方式:自定義執行緒繼承Thread類    同步程式碼塊  synchronized(被加鎖的物件){ 程式碼 }

public class Demo2{
	public static void main(String[] args) {
		Station station = new Station();
		TicketThread t1 = new TicketThread(station);
		TicketThread t2 = new TicketThread(station);
		t1.start();
		t2.start();
	}
}
class Station{
	private static int tickets = 20;//記錄車票的數量   使用static目的:確保2個視窗是共同在出售這20張票而不是這2個視窗各自出售20張 共出售40張
	//定義一個買票的方法
	public void getTicket(){
		synchronized (this) {
			if(tickets>0){
				System.out.println("車票還剩: "+ (--tickets) + "張 !");
			}
		}
	}
}
class TicketThread extends Thread{
	private Station station;
	public TicketThread(Station station) {
		this.station = station;
	}
	@Override
	public void run() {
		while(true){
			station.getTicket();
		}	
	}
}

第3種方式:自定義執行緒繼承Thread類    鎖機制lock

public class Demo3 {
	public static void main(String[] args) {
		Station station = new Station();
		TicketThread t1 = new TicketThread(station);
		TicketThread t2 = new TicketThread(station);
		t1.start();
		t2.start();
	}
}
class Station{
	private static int tickets = 20;//記錄車票的數量   使用static目的:確保2個視窗是共同在出售這20張票而不是這2個視窗各自出售20張 共出售40張
	// 1.建立Lock實現類的物件  注意:需在getTicket()方法外執行,如果在getTicket()方法裡執行,在getTicket()方法被呼叫的時候就會被建立很多ReentrantLock物件,即出現很多鎖
	ReentrantLock lock = new ReentrantLock();
	//定義一個買票的方法
	public void getTicket(){
		// 2.使用Lock物件的lock方法加鎖
		lock.lock();
		if(tickets>0){
			System.out.println("車票還剩: "+ (--tickets) + "張 !");
		}
		// 3.使用Lock物件的unlock方法解鎖
		lock.unlock();
	}
}
class TicketThread extends Thread{
	private Station station;
	public TicketThread(Station station) {
		this.station = station;
	}
	@Override
	public void run() {
		while(true){
			station.getTicket();
		}	
	}
}

第4種方式:自定義執行緒 實現Runnable介面    鎖機制lock

public class Demo4 {
	public static void main(String[] args) {
		Station station = new Station();
		TicketThread ticketThread1 = new TicketThread(station);
		TicketThread ticketThread2 = new TicketThread(station);
		Thread t1 = new Thread(ticketThread1);
		Thread t2 = new Thread(ticketThread2);
		t1.start();
		t2.start();
	}
}
class Station{
	private static int tickets = 20;//記錄車票的數量   使用static目的:確保2個視窗是共同在出售這20張票而不是這2個視窗各自出售20張 共出售40張
	// 1.建立Lock實現類的物件  注意:需在getTicket()方法外執行,如果在getTicket()方法裡執行,在getTicket()方法被呼叫的時候就會被建立很多ReentrantLock物件,即出現很多鎖
	ReentrantLock lock = new ReentrantLock();
	//定義一個買票的方法
	public void getTicket(){
		// 2.使用Lock物件的lock方法加鎖
		lock.lock();
		if(tickets>0){
			System.out.println("車票還剩: "+ (--tickets) + "張 !");
		}
		// 3.使用Lock物件的unlock方法解鎖
		lock.unlock();
	}
}
class TicketThread implements Runnable{
	private Station station;
	public TicketThread(Station station) {
		this.station = station;
	}
	@Override
	public void run() {
		while(true){
			station.getTicket();
		}	
	}
}

第5種方式:自定義執行緒 實現Runnable介面     同步方法 ==> 使用synchronized 修飾方法 

public class Demo5 {
	public static void main(String[] args) {
		Station station = new Station();
		TicketThread ticketThread1 = new TicketThread(station);
		TicketThread ticketThread2 = new TicketThread(station);
		Thread t1 = new Thread(ticketThread1);
		Thread t2 = new Thread(ticketThread2);
		t1.start();
		t2.start();
	}
}
class Station{
	private static int tickets = 20;//記錄車票的數量   使用static目的:確保2個視窗是共同在出售這20張票而不是這2個視窗各自出售20張 共出售40張
	//定義一個買票的方法
	public synchronized  void getTicket(){
		if(tickets>0){
			System.out.println("車票還剩: "+ (--tickets) + "張 !");
		}
	}
}
class TicketThread implements Runnable{
	private Station station;
	public TicketThread(Station station) {
		this.station = station;
	}
	@Override
	public void run() {
		while(true){
			station.getTicket();
		}	
	}
}

第6種方式:自定義執行緒 實現Runnable介面     同步程式碼塊  synchronized(被加鎖的物件){ 程式碼 }

public class Demo6 {
	public static void main(String[] args) {
		Station station = new Station();
		TicketThread ticketThread1 = new TicketThread(station);
		TicketThread ticketThread2 = new TicketThread(station);
		Thread t1 = new Thread(ticketThread1);
		Thread t2 = new Thread(ticketThread2);
		t1.start();
		t2.start();
	}
}
class Station{
	private static int tickets = 20;//記錄車票的數量   使用static目的:確保2個視窗是共同在出售這20張票而不是這2個視窗各自出售20張 共出售40張
	//定義一個買票的方法
	public void getTicket(){
		synchronized (this) {
			if(tickets>0){
				System.out.println("車票還剩: "+ (--tickets) + "張 !");
			}
		}
	}
}
class TicketThread implements Runnable{
	private Station station;
	public TicketThread(Station station) {
		this.station = station;
	}
	@Override
	public void run() {
		while(true){
			station.getTicket();
		}	
	}
}

 

相關文章