2017-07-26 31 views
-1

這是鍛鍊的要求:我需要實現與同步方法的Java程序,但我不能避免死鎖

  • 有3個房間S1,S2,S3,最大容量20,15,10
  • N多人都試圖在房間進入,如果房間都充滿等待
  • 在第一次訪問的每個人試圖在S1進入和等待,如果它的

  • 時一個人參觀了房間可以進入一個又一個,寧願一個不完整的房間,並沒有到過的房間

  • 一個人可以從一個房間不會退出,除非有其他可用的房間
  • 時訪問過的每個房間一個人結束訪華並打印訪問序列
  • 每個人在1秒5秒之前等待,然後嘗試更換房間
  • 每個房間的人數必須打印到所有訪問結束時。

在Java中使用同步方法。

這是我的代碼:

package com.company; 

public class Main { 

    public static void main(String[] args) throws InterruptedException { 
     final int N = 30; //people number (valore da cambiare anche all'attributo statico countPerson della classe Person) 
     Guide guide = new Guide(); 
     Person [] persons = new Person[N]; 

     System.out.println("Starting visit"); 
     for(int i = 0; i<N; i++){ 
      persons[i] = new Person(i, guide); 
      persons[i].start(); 
     } 


     while(Person.countPerson!=0) { 
      try { 
       Thread.sleep(1000); 
       System.out.println(" "); 
       for (int i=1; i<4; i++){ 
        System.out.print("There are "+ guide.countPeople(i)+" people in room number "+i+" ------"); 
       } 
      }catch (InterruptedException e){ 
       System.out.println("Thread main interrupted"); 
      } 
     } 
    } 
} 

class Guide{ 
    private int S1=20; 
    private int S2=15; 
    private int S3=10; 

    public synchronized int enterS1() throws InterruptedException{ 
     while (S1==0) 
      wait(); 
     S1--; 
     notifyAll(); 
     return 1; 
    } 

    public synchronized int enterS2() throws InterruptedException{ 
     while (S2==0) 
      wait(); 
     S2--; 
     notifyAll(); 
     return 2; 
    } 

    public synchronized int enterS3() throws InterruptedException{ 
     while (S3==0) 
      wait(); 
     S3--; 
     notifyAll(); 
     return 3; 
    } 

    public synchronized void exitRoom(int actualRoom){ 
     switch (actualRoom){ 
      case 1:{ 
       S1++; 
       notifyAll(); 
       break; 
      } 
      case 2:{ 
       S2++; 
       notifyAll(); 
       break; 
      } 
      case 3:{ 
       S3++; 
       notifyAll(); 
       break; 
      } 
     } 
    } 

    public int status(int room){ 
     switch (room){ 
      case 1:{ 
       return S1; 
      } 
      case 2:{ 
       return S2; 
      } 
      case 3:{ 
       return S3; 
      } 
      default:{ 
       return 999; 
      } 
     } 
    } 

    public int countPeople(int room){ 
     switch (room){ 
      case 1:{ 
       return 20-S1; 
      } 
      case 2:{ 
       return 15-S2; 
      } 
      case 3:{ 
       return 10-S3; 
      } 
      default:{ 
       return 999; 
      } 
     } 
    } 

} 

class Person extends Thread{ 
    private int id; 
    private Guide guide; 
    private boolean[] visited; 
    private int[] order; 
    private int actualRoom; 
    private boolean isFirstAccess; 
    private boolean visitTerminated; 
    private int counterOrder; 
    public static int countPerson=30; 

    public Person(int id, Guide guide) { 
     this.id = id; 
     this.guide = guide; 
     this.visited = new boolean[3]; 
     this.order = new int[3]; 
     this.actualRoom = 0; 
     this.isFirstAccess=true; 
     this.visitTerminated = false; 
     this.counterOrder=0; 

     for (int i = 0; i < 3; i++) { 
      visited[i] = false; 
      order[i] = 0; 
     } 
    } 


    @Override 
    public void run() { 
     while (!visitTerminated){ 
      try { 
       //start first access for this person 
       while(isFirstAccess){ 
        if(guide.status(1)!=0) { 
         actualRoom = guide.enterS1(); 
         if (actualRoom == 1) { 
          isFirstAccess = false; 
          visited[0] = true; 
          order[counterOrder]=1; 
          counterOrder++; 
          Thread.sleep((int)(Math.random()*4001)+1000); 
         } 
        } 
        else { 
         Thread.sleep((int)(Math.random()*4001)+1000); 
        } 
       } 
       //end first access for this person 

       if(guide.status(2)!=0 /*&& actualRoom!=2 */&& !visited[1]){ 
        guide.exitRoom(actualRoom); 
        actualRoom=guide.enterS2(); 
        visited[1]=true; 
        order[counterOrder]=2; 
        counterOrder++; 
        Thread.sleep((int)(Math.random()*4001)+1000); 

       } else if (guide.status(3)!=0 /*&& actualRoom!=3*/&& !visited[2]){ 
        guide.exitRoom(actualRoom); 
        actualRoom=guide.enterS3(); 
        visited[2]=true; 
        order[counterOrder]=3; 
        counterOrder++; 
        Thread.sleep((int)(Math.random()*4001)+1000); 

       } else if(guide.status(1)!=0 /*&& actualRoom!=1*/){ 
        guide.exitRoom(actualRoom); 
        actualRoom = guide.enterS1(); 
        Thread.sleep((int)(Math.random()*4001)+1000); 

       }else if(guide.status(2)!=0 /*&& actualRoom!=2*/){ 
        guide.exitRoom(actualRoom); 
        actualRoom=guide.enterS2(); 
        if(!visited[1]){ 
         visited[1]=true; 
         order[counterOrder]=2; 
         counterOrder++; 
        } 
        Thread.sleep((int)(Math.random()*4001)+1000); 

       } else if (guide.status(3)!=0 /*&& actualRoom!=3*/){ 
        guide.exitRoom(actualRoom); 
        actualRoom=guide.enterS3(); 
        if(!visited[2]){ 
         visited[2]=true; 
         order[counterOrder]=3; 
         counterOrder++; 
        } 
        Thread.sleep((int)(Math.random()*4001)+1000); 
       } 


       if(visited[0] && visited[1] && visited[2]){ 
        guide.exitRoom(actualRoom); 
        System.out.println("Person number "+this.id+" has terminated his visit. "+"Visiting order: "+order[0]+"-"+order[1]+"-"+order[2]); 
        visitTerminated=true; 
       } 
      }catch (InterruptedException e){ 
       System.out.println("Thread interrupted, people are leaving rooms "); 
       guide.exitRoom(actualRoom); 
      } 
     } 
     countPerson--; 
    } 
} 

如果N> 50我的程序死鎖進入,我不能修復它。你可以幫幫我嗎? 謝謝

+0

這個問題是更多的代碼審查的事情。他們可以給你一些有用的指針。這整個代碼都需要重建。特別是關於線程使用。 – Tschallacka

回答

1

在您的描述中你有以下容量S1=20, S2=15, S3=10。這總共提供了45個可用點。你也有一個約束,a person cannot exit from a room unless there are another available room

當你設置N = 50你填滿了所有房間,沒有人能夠離開他們當前的房間,因爲所有其他房間都已滿。所以是的 - 當N > 44時程序可能會掛起。

感謝@Robert指出該程序可能會終止爲N > 44

+0

我不會使用「意志」,但它可能會發生。 – Robert

+0

這取決於一個人在進入第一個房間之前是否還要等待1-5秒,否則他們都會在程序啓動後立即進入。如果不是所有的房間都會在第一個人試圖更換房間之前填滿。 – Jonas

+0

開始時只有S1會填滿:'在第一次訪問時,每個人嘗試進入S1並等待,如果它是 已滿' – Robert

相關問題