我正在尝试模拟参观者进入剧院并坐上一个可供使用的座位(共享可用座位的数量),一旦所有座位都被占用,其余的就进入睡眠状态。 我在访问者类内部的getsit方法中的availablesits变量上遇到了麻烦。 请帮助我
我尝试同步线程以及使变量可变。但是由于某些原因,所有线程同时到达该getit部分?我不明白为什么! //主要import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
int numVisitors = 23;
int theaterCapacity =5;
int party_ticket=3;
Clock clock = new Clock();
Theater theater=new Theater(theaterCapacity,clock);
ArrayList<Visitor> visitorlist = new ArrayList<Visitor>();
for(int i=1;i<=numVisitors;i++) {
visitorlist.add(new Visitor(i,clock,theater));
}
clock.start();
for(Visitor visitor:visitorlist)
visitor.start();
}
}
//访客班
public class Visitor extends Thread{
private static Clock clock;
private static Theater theater;
public int id;
public boolean sawPresentation=false;
public volatile int priority= 10;
public static long time = System.currentTimeMillis();
public void msg(String m) {
System.out.println("["+(System.currentTimeMillis()-time)+"] "+getName()+": "+m);
}
Visitor(int id, Clock clock, Theater theater){
this.id=id;
this.clock=clock;
this.theater=theater;
}
public void run(){
heArrives();
while(!sawPresentation) {
while(!clock.presentationIsOpen()) {
//busy wait
}
getASit();
}
}
public void heArrives() {
msg("the visitor arrived");
}
public synchronized void getASit(){
if(theater.availableSits>0){
msg("the visitor got a sit");
theater.availableSits--;
watchPresentation();
}
}
public void watchPresentation(){
msg("the visitor is watching the presentation");
}
}
//时钟类
import java.util.Timer;
import java.util.TimerTask;
public class Clock extends Thread {
public static long time = System.currentTimeMillis();
public static int secondsPassed=6;
Timer timer= new Timer();
TimerTask task = new TimerTask() {
@Override
public void run() {
secondsPassed++;
//System.out.println("seconds passed: "+secondsPassed);
}
};
public void run(){
timer.scheduleAtFixedRate(task,0,1000);
}
public boolean presentationIsOpen(){
if(secondsPassed%6==0) return true;
return false;
}
}
//剧院课
class Theater extends Thread{
public static Clock clock;
public int capacity;
public volatile int availableSits=5;
Theater(int capacity,Clock clock){
this.capacity=capacity;
this.clock=clock;
}
}
答案 0 :(得分:1)
您的主要问题是getASit方法的同步。您正在针对Visitor对象实例进行同步,因此每个线程都针对不同的对象进行了同步。相反,您必须针对共享的对象进行同步。就您而言,反对剧院。将您的方法更改为如下所示:
public void getASit(){
synchronized(theater){
if(theater.availableSits>0){
msg("the visitor got a sit");
theater.availableSits--;
watchPresentation();
}
}
}
最好不要使用繁忙的等待,它会消耗过多的CPU,例如,最好使用睡眠:
while(!clock.presentationIsOpen()) {
try {
Thread.sleep(1_000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}