2016-11-12 55 views
0

我想實現的東西喜歡 - 一個單獨的類持有型線的一些對象(教室2個Student對象),並存在持有一些靜態資源類(Resource.java) 。我在我的單例類中一個接一個地開始2個線程,並使它們消耗靜態資源。這發生在具有資源的類的同步方法中。在線程的run方法,我稱之爲上述同步方法和獲取輸出如下─實現與單共享資源算法中和多線程

輸出 -

請求巧克力:0
檢查如果有其他孩子的:是
塊結束
--Student 0結束運行---
請求從巧克力:1
檢查如果有其他孩子的:是
塊結束
我的問題是,在child_1完成同步塊的執行並執行sleep()之後,(thread_1休眠5秒,thread_2達到0秒)另一個線程(child_2) child_1喚醒因爲child_1不在child_1的同步塊和睡眠時間>然後child_2的執行時間之前)應該開始同步塊的執行。爲什麼child_1阻止其他人?

預期輸出 -
請求從巧克力:0
檢查如果可用其他兒童的:是
塊結束從
請求巧克力:1
檢查是否有其他兒童的可用的:是
塊結束
--Student 1點結束運行!---
--Student 0結束運行!---

我該如何做到這一點。

我的代碼file-- Singleton類(ClassRoom.java)

public class ClassRoom { 

private static ClassRoom instance = null; 
private static Student s[]; 

public static ClassRoom getInstance() { 
    if (instance == null) { 
     instance = new ClassRoom(); 
     initStudents(); 
    } 
    return instance; 
} 

private static void initStudents() { 
    s= new Student[2]; 
    s[0] = new Student(0,2,5); 
    s[1] = new Student(1,2,5); 
} 

public Student getStudent(int i) { 
    return s[i]; 
} 
} 

Student.java

public class Student extends Thread { 
int sid; 
int max_choco; 
int allo_choco; 
private Resource resource= new Resource(); 

public Student(int i, int j , int k) { 
    sid = i; 
    allo_choco = j; 
    max_choco = k; 
} 

@Override 
public void run() { 
    try { 
     resource.requestChocolate(sid, 2); 
     Thread.sleep(Math.abs(1-sid)*5000); 
     System.out.println("--Student "+sid+" finishes run!--- "); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
} 
public int getSid() { return sid;} 

@Override 
public String toString() { 
    return sid+" : "+allo_choco+" : "+max_choco; 
} 
} 

Resource.java

public class Resource { 

private static int total_chocolate = 10; 

public void requestChocolate(int id, int request) { 
    synchronized (Student.class) { 
     System.out.println("Request for chocolate from : "+ 
          ClassRoom.getInstance().getStudent(id).getSid()); 
     if(request <= total_chocolate) { 
      System.out.println("check if other childs available: " 
      +((ClassRoom.getInstance().getStudent((id+1)%2).getSid()>-1 
      && ClassRoom.getInstance().getStudent((id+1)%2).getSid()<3)?"Yes":"No")); { 
      } 
      total_chocolate-=request; 
     System.out.println("block ends"); 
     } else { 
      System.out.println("Request cannot be granted"); 
     } 
    } 
} 
} 

亞軍類(Test.java )

public class Test { 

public static void main(String args[]) { 
    ClassRoom room = ClassRoom.getInstance(); 
    for(int i = 0 ; i< 2; i++) { 
     room.getStudent(i).run(); 
    } 
} 
} 

回答

1

不正確開始Thread。您撥打run()的電話儘可能地同步:)。更改像這樣,它會工作:

ClassRoom room = ClassRoom.getInstance(); 
for(int i = 0 ; i< 2; i++) { 
     room.getStudent(i).start(); 
} 

什麼會通過調用start()發生的是,JVM將產生一個新的線程,然後調用run()方法進入該線程。很顯然,由於您重寫了run()這意味着您的代碼將會執行。區別在於,如果直接調用run(),那麼start()中的所有魔法都將丟失,並且調用將在與調用任何其他方法時發生的相同的線程中執行。

其他一些潛在的錯誤:

  • 在這種情況下,期望使Student實施Runnable而不是擴展Thread。做一個谷歌搜索來理解爲什麼。
  • 如果您不能保證只有一個線程使用ClassRoom,您的ClassRoom單例不是線程安全的,可能會在稍後創建錯誤。將同步添加到getInstance
+0

我正在調用run()而不是start()導致問題。我糾正它,並得到程序工作。謝啦!!!! 我花了很長時間弄清楚爲什麼它不工作.....再次感謝! –