多线程訪问共享数据(1)
多線程訪問共享數據解決方式:
一。什么是多線程
?線程是程序中一個單一的順序控制流程.在單個程序中同一時候運行多個線程完畢不同的工作,稱為多線程.
?全部的線程盡管在微觀上是串行運行的,可是在宏觀上你全然能夠覺得它們在并行運行
二。多線程訪問共享數據解決方式
1,假設每一個線程運行的代碼同樣,能夠使用同一個Runnable對象,這個Runnable對象中有那個共享數據。
比如:賣票系統。
2,假設每一個線程運行的代碼不同,這個時候須要用不同的Runnable對象,有例如以下三種方式來實現這些Runnable對象之間的數據共享:
??將共享數據封裝在另外一個對象中,然后將這個對象逐一傳遞給各個Runnable對象。每一個線程對共享數據的操作方法也分配到那個對象身上去完畢,這樣easy實現針對該數據進行的各個操作的相互排斥和通信。
??將這些Runnable對象作為某一個類中的內部類,共享數據作為這個外部類中的成員變量。每一個線程對共享數據的操作方法也分配給外部類,以便實現對共享數據進行的各種操作的相互排斥和通信。作為內部類的各個Runable對象調用外部類的這些方法。
????上面兩種方式的組合:將共享數據封裝在另外一個對象中,每一個線程對共享數據的操作方法也分配到那個對象身上去完畢,對象作為這個外部類中的成員變量或方法中的局部變量。每一個線程的Runnable對象作為外部類中的成員內部類或局部內部類。
??總之,要同步相互排斥的幾段代碼最好是分別放在幾個獨立的方法中這些方法再放在同一個類中,這樣比較easy實現他們之間的同步相互排斥和通信。
?
一個外部類A中有兩個內部類,這兩個內部類B、C怎樣共享數據?
——B、C都操作外部類A的同一個成員變量。所以。兩個Runnable對象要共享同一份數據,能夠把兩個Runnable作為外部類的內部類,把共享數據作為外部類的成員變量。
三。樣例:
1,假設每一個線程運行的代碼同樣。能夠使用同一個Runnable對象。這個Runnable對象中有那個共享數據。比如:賣票系統。
代碼解釋:開啟三個線程,同一時候訪問共享數據count。均對其進行--操作。實現思路:因為三個線程運行的代碼同樣(對共享數據的操作同樣)。所以使用同一個Runnable(例如以下代碼:類ShareData1實現Runnable接口),該Runnable對象中封裝了共享數據count。即對共享數據count的操作。
package com.tgb.thread07;/*** 多線程訪問共享對象和數據之——模擬賣票系統* 方案:因為買票時每一個線程運行的代碼同樣(均是在現有票數上--)。因此 能夠使用同一個Runnable對象,* 這個Runnable對象中有那個共享數據。比如:賣票系統。* * @author hanxuemin* @date 2015年7月30日10:06:35**/public class MultiThreadShareData {public static void main(String[] args) {ShareData1 data1 = new ShareData1();/*** 開啟三個線程,賣票,訪問共享數據*/new Thread(data1).start();new Thread(data1).start();new Thread(data1).start();}}/*** 包括共享數據的Runnable實現類ShareData1* * @author hanxuemin* */class ShareData1 implements Runnable {private int count = 100; // 票數總共100張(共享數據)public void run() {while (count > 0) {count--; // 票數-1System.out.println(Thread.currentThread().getName() + "買票后。票總數為:" + count);}}}
2。假設每一個線程運行的代碼不同,這個時候須要用不同的Runnable對象,有例如以下三種方式來實現這些Runnable對象之間的數據共享:
? ?方式一:將共享數據封裝在另外一個對象中,然后將這個對象逐一傳遞給各個Runnable對象。每一個線程對共享數據的操作方法也分配到那個對象身上去完畢。這樣easy實現針對該數據進行的各個操作的相互排斥和通信。
Demo:設計4個線程,當中兩個線程每次對j添加1,另外兩個線程對j每次降低1。寫出程序。
代碼解釋:(1)共享數據為j,兩個線程對其++,兩個線程對其--,因此運行的代碼不同,因此須要不同的Runnable對象;(2)看題得知4個線程對共享數據共兩種操作,所以創建兩個不同的Runnable實現類——MyRunnable1、MyRunnable2;(3)在創建類ShareData2,將共享數據封裝在該類中。同一時候封裝了每一個線程對共享數據的操作方法;(4)將ShareData2對象逐一傳遞給每一個Runnable對象。
* 分析:(1)對共享數據分別有兩個操作:<a>對共享數據j進行++;<b>對共享數據j進行--; ——所以 * 須要創建兩個Runnable對象(分別對j進行++ 和 --) * * @author hanxuemin * @date 2015年7月30日10:06:35 * */ public class MultiThreadShareData02 { public static void main(String[] args) { final ShareData2 data2 = new ShareData2();// 創建ShareData2實例對象(該對象中封裝了共享數據。和每一個線程對共享數據的操作方法) for (int i = 0; i < 2; i++) { /** * 創建兩個Runnable對象。將封裝了共享數據的data2對象逐一傳遞給這兩個Runnable對象 */ MyRunnable1 myRunnable1 = new MyRunnable1(data2); MyRunnable2 myRunnable2 = new MyRunnable2(data2); /** * 啟動兩個線程,這兩個線程使用兩個不同的Runnable */ new Thread(myRunnable1).start(); new Thread(myRunnable2).start(); } } } /** * MyRunnable1實現Runnable接口 * * @author hanxuemin * */ class MyRunnable1 implements Runnable { private ShareData2 data2; public MyRunnable1(ShareData2 data2) { this.data2 = data2; } @Override public void run() { data2.increment(); // 調用++方法 } } /** * MyRunnable2類實現Runnable接口 * * @author hanxuemin * */ class MyRunnable2 implements Runnable { private ShareData2 data2; public MyRunnable2(ShareData2 data2) { this.data2 = data2; } @Override public void run() { data2.decrement(); // 調用--方法 } } /** * 封裝了共享數據的類ShareData2。同一時候,該類封裝了每一個線程對共享數據的操作方法 * * @author hanxuemin * */ class ShareData2 { private int j = 100; // 共享數據j /** * 對j進行++的方法 */ public synchronized void increment() { j++; System.out.println("++方法:" + Thread.currentThread().getName() + "操作共享數據后。當前共享數據的值為" + j); } /** * 對j進行--的方法 */ public synchronized void decrement() { j--; System.out.println("--方法" + Thread.currentThread().getName() + "操作共享數據后,當前共享數據的值為" + j); } }
四,總結
不同是情況使用不同的解決方式。
另外兩種方式,見下一篇博客
總結
以上是生活随笔為你收集整理的多线程訪问共享数据(1)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 通过facade(尤其是realtime
- 下一篇: PC处理器装机中的认识 三