多個執行緒共享資料的方式
阿新 • • 發佈:2019-01-23
討論多個執行緒共享資料,其實就是討論多個執行緒如何對同一個資料進行操作。
另外,從今天開始,我會將我部落格中涉及到的原始碼放到我的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();
}
}
}