当线程使用共享类时,将条件放在哪里



我正在使用Threads复制教室,有一些条件需要设置

Lecturer在房间中时,Student不能进入或离开
  • 在所有Students都坐好之前,Lecturer不能开始上课
  • 讲座结束前学生不能离开
  • ClassroomStudents and Lecturers之间的共享类,所以这是我放置Conditions以使线程等待的地方。

    我对Conditions应该放在哪里感到困惑,它们应该放在Classroom类中吗?因为它们将在两个Lecturer/Student类中用于notify((。

    我在错误报告中的所有类中都得到java.lang.IollegalMonitorStateException

    Exception in thread "Thread-6" java.lang.IllegalMonitorStateException
    at java.base/java.lang.Object.notify(Native Method)
    at Classroom.allSeated(Classroom.java:87)
    at Student.sitDown(Student.java:70)
    at Student.run(Student.java:38)
    Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
    at java.base/java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:149)
    at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1302)
    at java.base/java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:439)
    at Classroom.waitToStartClass(Classroom.java:78)
    at Lecturer.startClass(Lecturer.java:43)
    at Lecturer.run(Lecturer.java:25)
    

    教室

    import java.util.Random;
    import java.util.concurrent.Semaphore;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class Classroom {
    private String name;
    private int capacity;
    
    private Semaphore teacherInRoom; // Binary Semaphore for Lecturer in a room
    private Semaphore semaphoreStudentVisitor;// Counting Semaphore for Visitors/Students in a room set to the capacity 
    
    private Lock lock= new ReentrantLock();
    private Condition startClass = lock.newCondition();
    private Condition classOver = lock.newCondition();;
    
    private boolean lecturerInRoom;
    private boolean allSitting;
    private boolean lectureStart;
    
    private int enteredStudents = 0;
    
    
    
    public Classroom(String name, int capacity) {
    this.name = name;
    this.capacity = capacity;   
    this.teacherInRoom = new Semaphore(1);// Control Lecturer in room
    this.semaphoreStudentVisitor = new Semaphore(capacity);// The amount of student allowed in a room at a time
    
    this.lecturerInRoom = false;
    this.allSitting = false;
    this.lectureStart = true;
    
    }
    
    
    // Name of room
    public String getName() {
    return name;
    }
    
    
    // Checks to see if the lecturer has entered the room
    public boolean checkIfLecturerInRoomStudent() {
    return lecturerInRoom;
    }
    
    
    // Check to see if students are all sitting
    public boolean checkIfStudentsAreSitting() {
    return allSitting;
    }
    // Check to see the number of students who have entered
    public int numberOfStudentsInRoom() {
    return enteredStudents;
    }
    
    // Check to see if lecture has started
    public boolean haslectureStarted() {
    return lectureStart;
    }
    
    
    // Used to make the Lecturer wait on the condition startClass
    public void waitToStartClass() {
    try {
    while(!checkIfStudentsAreSitting()) {
    try {
    startClass.await();
    }catch (InterruptedException e) {}
    }
    }finally {
    lock.unlock();
    }
    }
    
    // THIS IS WHERE THE java.lang.IllegalMonitorStateException is thrown
    // Called to notify the Lecturer that all of the students are sitting 
    public void allSeated() {
    lock.lock();
    try {
    startClass.notify();
    }finally {
    lock.unlock();
    }
    }
    
    
    
    
    // Controls the semaphores for the room 
    // No more threads than room capacity
    // No more than 1 lecturer per room
    public void lecturerSemaphoreEntered() {
    try {
    lecturerInRoom = true;
    teacherInRoom.acquire();
    }
    catch (InterruptedException e) {}
    }
    
    public void lecturerSemaphoreLeave() {
    teacherInRoom.release();
    lecturerInRoom = false;
    }
    
    
    
    public void studentVisitorsSemaphoreEntered() {
    try {
    semaphoreStudentVisitor.acquire();
    enteredStudents++;
    }
    catch (InterruptedException e) {
    // TODO: handle exception
    }
    }
    
    public void studentVisitorsSemaphoreLeave() {
    semaphoreStudentVisitor.release();
    enteredStudents--;
    }
    
    // Create a random index for the classroom to enter
    static int classRoomNumber (int lengthOfArray) {
    Random rand = new Random();
    int roomNumber = rand.nextInt(lengthOfArray);
    return roomNumber;
    }
    
    
    }
    

    讲师

    import java.util.Random;
    import java.util.concurrent.Semaphore;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class Lecturer extends Thread{
    private final String name;
    private Classroom classroomList [];
    private Lock lock = new ReentrantLock();
    
    public Lecturer(String name, Classroom  [] classroom) {
    this.name = name;
    this.classroomList = classroom;
    }
    
    @Override
    public void run() {
    while(true) {
    int timeInRoom = (int) (Math.random() * 10000);
    Classroom classroom = classroomList[Classroom.classRoomNumber(classroomList.length)];  // Create random number for room to enter
    enter(classroom);
    
    startClass(classroom);
    
    leave(classroom);
    
    }
    }
    
    //Calls the methods in Classroom for semaphores and condition 
    private void enter(Classroom classroom) {
    classroom.lecturerSemaphoreEntered();
    }
    private void leave(Classroom classroom) {
    classroom.lecturerSemaphoreLeave();
    }
    
    private void startClass(Classroom classroom) {
    classroom.waitToStartClass();
    }
    
    }
    

    sitDown()被称为时,也会出现错误

    学生

    import java.util.Random;
    import java.util.concurrent.Semaphore;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    public class Student extends Thread{
    private Classroom classroomList[];
    static volatile int sitting = 0;
    
    
    volatile Lock lock = new ReentrantLock();
    
    
    public Student(Classroom[] classroomList) {
    this.classroomList = classroomList;
    }
    
    @Override
    public void run() {
    while(true) {
    int timeInRoom = (int) (Math.random() * 5000);
    Classroom classroom = classroomList[Classroom.classRoomNumber(classroomList.length)]; 
    if(!classroom.checkIfLecturerInRoomStudent()) {
    enter(classroom);
    
    
    
    if(classroom.checkIfLecturerInRoomStudent()) {
    // Counting so all of the students can sit
    while(sitting < classroom.numberOfStudentsInRoom()) {
    sitting++;
    }                   
    //Here all students are sitting
    sitDown(classroom);
    }
    
    
    
    
    sitting = 0;
    leave(classroom);
    }
    
    
    
    }
    
    
    }
    
    // Uses the Semaphore in the Classroom to control the students in the room
    // also it increments the number of current students
    synchronized void enter(Classroom classroom) {
    classroom.studentVisitorsSemaphoreEntered();
    }
    
    // Uses the Semaphore in the Classroom to control the students in the room
    // also it decrements the number of current students
    synchronized void leave(Classroom classroom) {
    classroom.studentVisitorsSemaphoreLeave();
    }
    
    // Uses the Semaphore in the Classroom to control the students in the room
    // also it decrements the number of current students
    synchronized void sitDown(Classroom classroom) {
    classroom.allSeated();
    }
    
    }
    

    由于您正在同步块之外调用notify of condition方法,因此引发了异常。这个方法来自Object类,您需要调用signal或signalAll,这是Condition的方法来通知。

    最新更新