JAVA基礎——多線程

  1. 線程安全

如果有多個線程在同時運行,而這些線程可能會同時運行這段代碼。程序每次運行結果和單線程運行的結果是一樣的,而且其他的變量的值也和預期的是一樣的,就是線程安全的

我們通過一個案例,演示線程的安全問題:

電影院要賣票,我們模擬電影院的賣票過程。假設要播放的電影是 “功夫熊貓3”,本次電影的座位共100個(本場電影只能賣100張票)。

我們來模擬電影院的售票窗口,實現多個窗口同時賣 “功夫熊貓3”這場電影票(多個窗口一起賣這100張票)

需要窗口,採用線程對象來模擬;需要票,Runnable接口子類來模擬

測試類

public class ThreadDemo {

public static void main(String[] args) {

//創建票對象

Ticket ticket = new Ticket();

 

//創建3個窗口

Thread t1  = new Thread(ticket, "窗口1");

Thread t2  = new Thread(ticket, "窗口2");

Thread t3  = new Thread(ticket, "窗口3");

 

t1.start();

t2.start();

t3.start();

}

}

  1. 模擬票

public class Ticket implements Runnable {

//共100票

int ticket = 100;

 

@Override

public void run() {

//模擬賣票

while(true){

if (ticket > 0) {

//模擬選坐的操作

try {

Thread.sleep(1);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName() + "正在賣票:" + ticket--);

}

}

}

}

運行結果發現:上面程序出現了問題

票出現了重複的票

錯誤的票 0、-1

 

其實,線程安全問題都是由全局變量及靜態變量引起的。若每個線程中對全局變量、靜態變量只有讀操作,而無寫操作,一般來說,這個全局變量是線程安全的;若有多個線程同時執行寫操作,一般都需要考慮線程同步,否則的話就可能影響線程安全。

 

2.線程同步(線程安全處理Synchronized)

java中提供了線程同步機制,它能夠解決上述的線程安全問題。

線程同步的方式有兩種:

  1. 方式1:同步代碼塊
  2. 方式2:同步方法

同步代碼塊

同步代碼塊: 在代碼塊聲明上 加上synchronized

synchronized (鎖對象) {

可能會產生線程安全問題的代碼

}

同步代碼塊中的鎖對象可以是任意的對象;但多個線程時,要使用同一個鎖對象才能夠保證線程安全。

 

使用同步代碼塊,對電影院賣票案例中Ticket類進行如下代碼修改:

public class Ticket implements Runnable {

//共100票

int ticket = 100;

//定義對象

Object lock = new Object();

@Override

public void run() {

//模擬賣票

while(true){

//同步代碼塊

synchronized (lock){

if (ticket > 0) {

//模擬電影選坐的操作

try {

Thread.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName() + "正在賣票:" + ticket--);

}

}

}

}

}

當使用了同步代碼塊後,上述的線程的安全問題,解決了。

​​​​​​​​​​​​​​同步方法

  1. 同步方法:在方法聲明上加上synchronized

public synchronized void method(){

    可能會產生線程安全問題的代碼

}

同步方法中的鎖對象是 this

 

使用同步方法,對電影院賣票案例中Ticket類進行如下代碼修改:

public class Ticket implements Runnable {

//共100票

int ticket = 100;

//定義對象

Object lock = new Object();

@Override

public void run() {

//模擬賣票

while(true){

//同步方法

method();

}

}

 

//同步方法,鎖對象this

public synchronized void method(){

if (ticket > 0) {

//模擬選坐的操作

try {

Thread.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName() + "正在賣票:" + ticket--);

}

}

}

 

  1. 靜態同步方法: 在方法聲明上加上static synchronized

public static synchronized void method(){

可能會產生線程安全問題的代碼

}

靜態同步方法中的鎖對象是 類名.class

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章