有一個使用共同數據的經驗:要用到共同數據(包括同步鎖)的若干方法,要放到同一個類裡。體現了程序的高內聚,也增強了程序的健壯性。
還有一個經驗,把同步代碼或在和鎖放到共同使用的數據上,而不是放在線程內,這樣的好處是什麼呢:首先是更符合面向對象的思想。其次是這種設計結構非常容易實現線程的同步,並且增加線程訪問共同數據的時候不用每次都在線程內增加同步代碼。有利於擴展和維護。
首先看一個例子,子線程先循環10次,主線程再循環100次,接著子線程循環10次,主線程再循環100次,如此循環往復50次;
實現代碼如下:
[java]
- public class TraditionalThreadConnection {
-
- /**
- * @param args
- */
- public static void main(String[] args) {
-
- final Service service = new Service();
- //子線程
- new Thread(new Runnable(){
-
- @Override
- public void run() {
- for(int i = 1;i<=50;i++){
- service.subThread(i);
- }
- }
-
- }).start();
- //主線程
- for(int i = 1;i<=50;i++){
- service.mainThread(i);
- }
- }
-
-
- }
- class Service{
- /* 是否該子線程運行的標志 */
- private boolean isSub = true;
- public synchronized void subThread(int loop){
- //首先是判斷是否該子線程運行,不是就等待
- while(!isSub){
- try {
- this.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- for(int i=1;i<=10;i++){
- System.out.println("sub-thread-" + i + ",loop--" + loop);
- }
- isSub = false;
- //子線程運行完之後叫醒主線程
- this.notify();
- }
- public synchronized void mainThread(int loop){
- while(isSub){
- try {
- this.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- for(int i=1;i<=100;i++){
- System.out.println("main-thread-" + i + ",loop--" + loop);
- }
- isSub = true;
- this.notify();
- }
- }
還有一點要注意的地方,就在判斷是否等待的地方為什麼用到while而不是if:原因是這樣的,因為使用wait的時候有可能在沒有調用notify的時候自己就喚醒了,開始去執行代碼了,這叫做假喚醒。使用while就可以避免偽喚醒帶來的災難,還可以判斷一下是否可以去執行代碼。