java—线程使用共享类时将条件放在何处

unftdfkk  于 2021-06-29  发布在  Java
关注(0)|答案(1)|浏览(260)

我复制了一个教室使用线程有几个条件,需要设置 Student 不能进入或离开时 Lecturer 在房间里
Lecturer 不能开始上课,直到所有 Students 坐过
学生们在讲座结束前不能离开
Classroom 是一个共享类 Students and Lecturers 所以这就是我把我的 Conditions 使线程等待。
我搞不懂条件应该去哪里,应该去哪里 Classroom 类,因为它们将用于 Lecturer/Student 类通知()。
我在错误报告中的所有类中都得到java.lang.illegalmonitorstateexception

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();
    }

}
yqlxgs2m

yqlxgs2m1#

已引发异常,因为您正在同步块外部调用notify of condition方法。这个方法是来自对象类,你需要调用signal或signalall,这是通知条件的方法。

相关问题