1. 程式人生 > >多個執行緒共享資料的方式

多個執行緒共享資料的方式

討論多個執行緒共享資料,其實就是討論多個執行緒如何對同一個資料進行操作。

另外,從今天開始,我會將我部落格中涉及到的原始碼放到我的github中。

方式有很多,這裡列出2種:

1.每個執行緒執行的程式碼相同

如果每個執行緒執行的程式碼相同,可以使用同一個Runnable物件,這個物件中有那個我們需要共享的資料,例如我們的賣票系統。

示例Demo:



public class ManyCenjoyOneob
{

    public static void main(String[] args)
    {
        AllenjoyOb demo = new AllenjoyOb();

        Thread th1 = new
Thread(demo); Thread th2 = new Thread(demo); th1.start(); th2.start(); } } class AllenjoyOb implements Runnable { private int data = 0; @Override public void run() { increment(); } private void increment() { data++; } }

分析:我們將data作為共享資料,然後作為Runnable物件的一個成員變數,構造執行緒的時候使用同一個Runnable物件,然後就可以使用多執行緒共同操作同一個data了。

2.共享資料封裝在另外一個實現Runnable介面的類中

示例Demo:


public class ManyCenjoyOneob
{

    public static void main(String[] args)
    {
        //第一種方式
        AllenjoyOb demo = new AllenjoyOb();

        Thread th1 = new Thread(demo);
        Thread th2 = new
Thread(demo); th1.start(); th2.start(); //第二種方式 int data = 0; Thread thA = new Thread(new XXXX2(data)); Thread thB = new Thread(new XXXX2(data)); thA.start(); thB.start(); } } //第一種方式使用的類程式碼 class AllenjoyOb implements Runnable { private int data = 0; @Override public void run() { increment(); } private void increment() { data++; } } //第二種方式使用的類的程式碼 class XXXX2 implements Runnable { private int data2 = 0; public XXXX2(int data2) { this.data2 = data2; } @Override public void run() { increment2(); } private void increment2() { data2++; } }

最後,我們來看一個常見的面試題:

題目如下:設計四個執行緒,其中2個執行緒每次對j增加1,另外2個對j每次減少1。

分析:依照前面我們對程式碼分塊的原則,我們將執行緒分成2部分,一部分是來負責增加操作,另一部分是負責減少操作。為了使程式碼看起來條理清楚,我們將增加和減少這2個操作也獨立成方法。然後還有主程式用來呼叫執行緒。另外,還有j需要執行緒共享,於是我們將j放在類的成員變數中,用內部類的方式來操作j,畢竟內部類可以操作類的成員變數。程式碼如下:


public class FourThreadIncJDecJ
{

    private int j = 0;   //將j作為主類的成員變數,

    public static void main(String[] args)
    {
        FourThreadIncJDecJ demo = new FourThreadIncJDecJ();//例項化一個主類物件,一是可以方便建立內部類物件,二是可以得到一個j資料

        Inc incRunnable = demo.new Inc();                       //這裡應當注意,內部類物件的建立依賴於寄生的那個主類的物件!
        Dec decRunnable = demo.new Dec();

        for(int i = 0;i<2;i++)
        {

            Thread thread = new Thread(incRunnable);
            thread.start();

            thread = new Thread(decRunnable);
            thread.start();


        }

    }

    //increment Operation
    public synchronized void IncOp()
    {
        j++;

        System.out.println(Thread.currentThread().getName()+"+ inc :"+j);
    }

    //Dec Operation
    public synchronized void DecOp()
    {
        j--;
        System.out.println(Thread.currentThread().getName()+"+ dec :"+j);
    }



    class Inc implements Runnable
    {

        @Override
        public void run()
        {
            IncOp();
        }
    }

    class Dec implements Runnable
    {
        @Override
        public void run()
        {
            DecOp();
        }
    }
}