2016-11-12 54 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()导致问题。我纠正它,并得到程序工作。谢啦!!!! 我花了很长时间弄清楚为什么它不工作.....再次感谢! –