我正在学习多线程。这是我的第一个任务。我写了这段代码,我无法继续前进。任务:
容量相等的滑雪缆车N. 客户端具有权重(随机Ki值),它们是执行的线程 循环:
如果成功了 - 他们会上去。
public class Client extends Thread { private SkiLift lift; private int weight;public Client(SkiLift l, int w) { this.lift = l; this.weight=w; } public int getWeight() { return weight; } public void run() { for (int i =0; i<10; i++) { lift.downhill(this); lift.goIn(this); this.setPriority(MAX_PRIORITY); lift.drive(this); lift.goOut(this); this.setPriority(5); } }
} public class SkiLift { private static int actualLoad=0; private static final int CAPACITY=300;
synchronized public void goIn(Client client) { try { System.out.println("Client " + client.getId() + " try to get into the lift"); while (actualLoad>CAPACITY) { System.out.println("The Lift is full!"); client.sleep((long) (Math.random()*1000)); wait(); } } catch (InterruptedException e) {} System.out.println("Client " + client.getId() + "get into the lift " ); actualLoad+=client.getWeight(); System.out.println("actual load = " + actualLoad); } synchronized public void goOut (Client client) { System.out.println("Client "+ client.getId() + " leave the lift "); actualLoad-=client.getWeight(); System.out.println("Actual load = " + actualLoad); notifyAll(); } public void downhill(Client client) { System.out.println("Client nr: " + client.getId()+ " downhill "); try { client.sleep((long) (Math.random()*10000)); } catch (InterruptedException e){} } public void drive(Client client) { try { client.sleep(9000); } catch (InterruptedException e){e.printStackTrace();} }
}
我有三个问题,我无法解决它们:
提前致谢:)
答案 0 :(得分:0)
显然,系统中的瓶颈是电梯。电梯只能有N个并发用户。
另外,3。提到了一个监视器。在阅读了显示器的内容之后,您应该弄清楚它允许独占访问有限的资源,即电梯。
因此,设计您的电梯访问权限以尝试获取N个显示器中的一个,等待一段时间,最后不要忘记释放显示器,以便其他人可以获得它。
答案 1 :(得分:0)
我认为这个问题属于Codereview
您的客户应该拥有“topOfTheMountainReached”,“liftStationReached”,“liftEntered”等状态......
您的客户等待此事件发生。这也是你的问题的答案,要监控哪个元素 - 国家或客户本身。
对于队列,您可以使用ArrayListBlockingQueue
。
然后,您的SkiLift必须等待新客户到达并将其放入电梯。一旦客户进入电梯,客户也会收到通知它已进入电梯的通知。当达到顶部时,Lift还会通知客户端。
以下是此类解决方案的外观示例。 它使用Java Executor服务来安排事件,使客户端离开电梯,并在下坡部分的末端到达电梯站。这也可以用不同的方式解决。
客户:
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Client implements Runnable{
final ScheduledExecutorService dhexceutors = Executors.newScheduledThreadPool(500);
final static Random DHRANDOM = new Random();
final long weight;
public enum State {
goDownhill,
waitForLift,
goUp,
onTop,
}
private State state;
public SkiLift lift;
public Client(long weight,SkiLift lift) {
this.lift = lift;
this.weight = weight;
this.state = State.onTop;
goDownHill();
}
private void enterLift() {
lift.add(this);
}
private void goDownHill() {
synchronized (this) {
state = State.goDownhill;
this.notify();
}
dhexceutors.schedule(() -> {
liftStationReached();
}, DHRANDOM.nextInt(500), TimeUnit.MILLISECONDS);
}
public void liftStationReached() {
synchronized(this) {
state = State.waitForLift;
this.notify();
}
}
public void topReached() {
synchronized(this) {
state = State.onTop;
this.notify();
}
}
public void liftEntered() {
synchronized(this) {
state = State.goUp;
this.notify();
}
}
public void run() {
synchronized(this) {
while (true) {
try {
this.wait();
switch (state) {
case waitForLift:
enterLift();
break;
case goUp:
// just wait for the topReached event
break;
case goDownhill:
// just wait for reaching the lift.
break;
case onTop:
goDownHill();
break;
}
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
}
}
}
}
电梯:
package skilift;
import java.util.ArrayList;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class SkiLift implements Runnable{
private ScheduledExecutorService getOutClientExecutor;
public SkiLift() {
getOutClientExecutor = Executors.newScheduledThreadPool(50);
waitingClientsQueue = new ArrayBlockingQueue<>(1000);
occupiedSeats = new ArrayList<>();
}
private final ArrayList<Client> occupiedSeats;
private long usedCapacity;
private final ArrayBlockingQueue<Client> waitingClientsQueue;
private final long capacity = 500;
public void add(Client client) {
synchronized(waitingClientsQueue) {
waitingClientsQueue.add(client);
waitingClientsQueue.notify();
}
}
private synchronized void occupySeat(Client client) {
occupiedSeats.add(client);
usedCapacity += client.weight;
}
private synchronized void getClientOut(Client client) {
occupiedSeats.remove(client);
usedCapacity -= client.weight;
// notify the waitingClientQueue that the capacity has changed
synchronized (waitingClientsQueue) {
waitingClientsQueue.notify();
}
client.topReached();
}
public void run() {
while (true) {
synchronized(waitingClientsQueue) {
try {
if (!waitingClientsQueue.isEmpty()) {
Client c = waitingClientsQueue.peek();
if (usedCapacity + c.weight <= capacity) {
occupySeat(waitingClientsQueue.poll());
getOutClientExecutor.schedule(() -> {
getClientOut(c);
}, 2, TimeUnit.SECONDS);
} else {
waitingClientsQueue.wait();
}
} else {
waitingClientsQueue.wait();
}
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
}
}
}
}