package android.java.thread09; /** * 售票線程 */ class Booking implements Runnable { /** * 模擬票的總算 10張票 */ private int ticket = 10; @Override public void run() { while (true) { if (ticket > 0) { // 讓線程在這裏停一下,會更加容易復現線程的安全問題,就算不加這行代碼,安全問題依然有 try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("名稱:" + Thread.currentThread().getName() + "窗口賣出第" + ticket + "張票"); ticket--; } } } } /** * 售票案例 */ public class BookingTest { public static void main(String[] args) { /** * 定義Runnable實現類Booking,此實現類Booking不是線程,此實現類Booking給四個Thread去執行的 */ Runnable booking = new Booking(); // 實例化線程對象 Thread thread1 = new Thread(booking); // 此實現類Booking給Thread去執行的 Thread thread2 = new Thread(booking); // 此實現類Booking給Thread去執行的 Thread thread3 = new Thread(booking); // 此實現類Booking給Thread去執行的 Thread thread4 = new Thread(booking); // 此實現類Booking給Thread去執行的 // 開啓啓動線程 thread1.start(); // 啓動第Thread-0窗口 執行賣票任務 thread2.start(); // 啓動第Thread-1窗口 執行賣票任務 thread3.start(); // 啓動第Thread-2窗口 執行賣票任務 thread4.start(); // 啓動第Thread-3窗口 執行賣票任務 } }
名稱:Thread-0窗口賣出第10張票
名稱:Thread-3窗口賣出第9張票
名稱:Thread-1窗口賣出第8張票
名稱:Thread-2窗口賣出第7張票
名稱:Thread-0窗口賣出第6張票
名稱:Thread-3窗口賣出第5張票
名稱:Thread-2窗口賣出第4張票
名稱:Thread-1窗口賣出第4張票
名稱:Thread-2窗口賣出第2張票
名稱:Thread-0窗口賣出第1張票
名稱:Thread-3窗口賣出第1張票
名稱:Thread-1窗口賣出第-1張票
名稱:Thread-2窗口賣出第-2張票java
CPU的隨機性,到底切換到哪一個線程,到底執行哪一個線程代碼的多少行,等等,都是隨機的android
1.線程任務中,發現有共享數據,例如:ticket。安全
2.多線程操做共享數據,例如:ticket。多線程
形成的緣由是:Thread-0在對共享數據操做過程當中,CPU執行了Thread-1對共享數據操做, 至關於:我在數錢,忽然我出去有事了,而後有我的拿了500塊錢,等我在回來數錢的時候,就已經發生是數據安全問題ide
package android.java.thread09; /** * 售票線程 */ class Booking implements Runnable { /** * 模擬票的總算 10張票 */ private int ticket = 10; @Override public void run() { while (true) { /** * 加入了同步代碼塊的代碼synchronized, * 無論CPU如何瘋狂的切換執行, * 只要同步代碼塊裏面的代碼沒有執行完, * 就不許其餘線程進來執行 * 這樣就保證了多線程操做共享數據的安全新 */ synchronized (Booking.class) { // 同步操做共享數據的代碼 if (ticket > 0) { // 讓線程在這裏停一下,會更加容易復現線程的安全問題,就算不加這行代碼,安全問題依然有 try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("名稱:" + Thread.currentThread().getName() + "窗口賣出第" + ticket + "張票"); ticket--; } } } } } /** * 售票案例 */ public class BookingTest { public static void main(String[] args) { /** * 定義Runnable實現類Booking,此實現類Booking不是線程,此實現類Booking給四個Thread去執行的 */ Runnable booking = new Booking(); // 實例化線程對象 Thread thread1 = new Thread(booking); // 此實現類Booking給Thread去執行的 Thread thread2 = new Thread(booking); // 此實現類Booking給Thread去執行的 Thread thread3 = new Thread(booking); // 此實現類Booking給Thread去執行的 Thread thread4 = new Thread(booking); // 此實現類Booking給Thread去執行的 // 開啓啓動線程 thread1.start(); // 啓動第Thread-0窗口 執行賣票任務 thread2.start(); // 啓動第Thread-1窗口 執行賣票任務 thread3.start(); // 啓動第Thread-2窗口 執行賣票任務 thread4.start(); // 啓動第Thread-3窗口 執行賣票任務 } }
.........spa