我复制了一个教室使用线程有几个条件,需要设置 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();
}
}
1条答案
按热度按时间yqlxgs2m1#
已引发异常,因为您正在同步块外部调用notify of condition方法。这个方法是来自对象类,你需要调用signal或signalall,这是通知条件的方法。