【線程實現的兩種方式及區別】


我們來用最經典的賣票的案例,表明兩種實現方式的區別,同時分析線程不安全產生的原因

一、繼承Thread類

package test;

/**
 * @Description
 * @Author shusheng
 * @Email shusheng@yiji.com
 * @Date 2018/8/31
 */
public class SellTicketOne extends Thread{

    private static int tickets = 100;

    @Override
    public void run(){
        while(true){
            if(tickets>0){
                System.out.println(getName()+"正在出售第"+tickets+"張票");
                tickets--;
            }
        }
    }

}

二、實現Runnable接口

package test;

/**
 * @Description
 * @Author shusheng
 * @Email shusheng@yiji.com
 * @Date 2018/8/31
 */
public class SellTicketTwo implements Runnable{

    private static int tickets = 100;

    @Override
    public void run(){
        while(true){
            if(tickets>0){
                System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"張票");
                tickets--;
            }
        }
    }

}

啟動線程

package test;

/**
 * @Description
 * @Author shusheng
 * @Email shusheng@yiji.com
 * @Date 2018/8/31
 */
public class SellTicketTest {

    public static void main(String[] args) {

        SellTicketOne one1 = new SellTicketOne();
        SellTicketOne one2 = new SellTicketOne();
        SellTicketOne one3 = new SellTicketOne();
        one1.setName("窗口一");
        one2.setName("窗口二");
        one3.setName("窗口三");
        one1.start();
        one2.start();
        one3.start();

        SellTicketTwo two = new SellTicketTwo();
        Thread t1 = new Thread(two,"窗口四");
        Thread t2 = new Thread(two,"窗口五");
        Thread t3 = new Thread(two,"窗口六");
        t1.start();
        t2.start();
        t3.start();

    }
}

可以看到,二者的主要區別是:

1.實現Runnable接口的方式可以避免由於JAVA單繼承帶來局限性

2.實現Runnable接口的方式,適用多個相同程序的代碼去處理同一個資源的情況,把線程同程序的代碼、數據有效分離,較好的體現了面向對象的設計思想。

 

加上每次賣票延遲200毫秒,運行程序,發現兩個問題:

A:相同的票賣了多次:CPU的一次操作必須是原子性

B:出現了負數票:隨機性和延遲導致的

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM