如何在兩個線程間共享數據?


如果一個類繼承Thread,則不適合資源共享。但是如果實現了Runable接口的話,則很容易的實現資源共享。實現Runnable接口或callable接口,適合多個相同或不同的程序代碼的線程去共享同一個資源。

多個線程共享數據分兩種情況:

1、如果多個線程執行同一個Runnable實現類中的代碼,此時共享的數據放在Runnable實現類中;

2、如果多個線程執行不同的Runnable實現類中的代碼,此時共享數據和操作共享數據的方法封裝到一個對象中,在不同的Runnable實現類中調用操作共享數據的方法。

一、 相同程序代碼的多個線程共享一個資源

如果有多個線程在同時運行同一段段代碼,可以使用同一個Runnable實現類,多個線程可以共享一個實現類對象,共享數據作為這個Runnable實現類的全局變量

賣票案例:

public class Demo08 {
    public static void main(String[] args) {
        //創建線程任務對象

        Ticket ticket = new Ticket();
        //創建三個窗口對象
        Thread t1 = new Thread(ticket, "窗口1");
        Thread t2 = new Thread(ticket, "窗口2");
        Thread t3 = new Thread(ticket, "窗口3");
        //賣票
        t1.start();
        t2.start();
        t3.start();
    }
    static class Ticket implements Runnable {
        //Object lock = new Object();
        ReentrantLock lock = new ReentrantLock();
        private int ticket = 10;
        public void run() {
            String name = Thread.currentThread().getName();
            while (true) {
                sell(name);
                if (ticket <= 0) {
                    break;
                }
            }
        }
        private synchronized void sell(String name) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }if (ticket > 0) {
                System.out.println(name + "賣票:" + ticket);
                ticket--;
            }
        }
    }
}

ticket就是全局變量,作為三個線程的共享數據。

二、 不同程序代碼的多個線程共享一個資源

如果每個線程執行的代碼不同,將共享數據和操作共享數據的方法封裝在一個對象中,在不同的Runnable實現類調用操作共享數據的方法。

銀行轉賬案例:

創建一個對象,對象中有操作共享數據的方法

public class Bank {

    private volatile int count =0;//賬戶余額

    //存錢
    public  void addMoney(int money){
        count +=money;
        System.out.println(System.currentTimeMillis()+"存進:"+money);
    }

    //取錢
    public  void subMoney(int money){
        if(count-money < 0){
            System.out.println("余額不足");
            return;
        }
        count -=money;
        System.out.println(+System.currentTimeMillis()+"取出:"+money);
    }

    //查詢
    public void lookMoney(){
        System.out.println("賬戶余額:"+count);
    }
}

創建兩個線程,線程中分別調用共享數據所在對象中不同的方法,

public class SyncThreadTest {

    public static void main(String args[]){
        final Bank bank=new Bank();

        Thread tadd=new Thread(new Runnable() {

            public void run() {
                // TODO Auto-generated method stub
                while(true){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    bank.addMoney(100);
                    bank.lookMoney();
                    System.out.println("\n");

                }
            }
        });

        Thread tsub = new Thread(new Runnable() {

            public void run() {
                // TODO Auto-generated method stub
                while(true){
                   bank.subMoney(100);
                    bank.lookMoney();
                    System.out.println("\n");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        });
        tsub.start();
        tadd.start();
    }
}

如果一個類繼承Thread,則不適合資源共享。並不是不可以實現資源共享

生產者與消費者問題

包子鋪線程生產包子,吃貨線程消費包子。當包子沒有時(包子狀態為false),吃貨線程等待,包子鋪線程生產包子(即包子狀態為true),並通知吃貨線程(解除吃貨的等待狀態),因為已經有包子了,那么包子鋪線程進入等待狀態。接下來,吃貨線程能否進一步執行則取決於鎖的獲取情況。如果吃貨獲取到鎖,那么就執行吃包子動作,包子吃完(包子狀態為false),並通知包子鋪線程(解除包子鋪的等待狀態),吃貨線程進入等待。包子鋪線程能否進一步執行則取決於鎖的獲取情況。

包子資源類:
吃貨線程類:
包子鋪線程類:

 

實現Runnable接口比繼承Thread類所具有的優勢:

1. 適合多個相同的程序代碼的線程去共享同一個資源。

2. 可以避免java中的單繼承的局限性。

3. 增加程序的健壯性,實現解耦操作,代碼可以被多個線程共享,代碼和線程獨立

4. 線程池只能放入實現Runable或Callable類線程,不能直接放入繼承Thread的類。

 


免責聲明!

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



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