寻找适合此问题的同步Java代码 公共汽车车手公交车站管理器用法

问题描述

问题

车手来到公交车站等车。公交车到达时,所有等待的车手都调用boardBus,但是在公交车上车时到达的任何人都必须等待下一辆公交车。公交车可容纳50人;如果有 有超过50人在等待,有些人将不得不等待下一辆公共汽车。当所有等待的车手都登上车后,巴士便可以出发。如果在没有乘客的情况下到达公共汽车,则应立即出发。请注意,公交车和骑士将全天继续到达。假设公交车和骑手的到站时间分别以平均20分钟和30秒的指数分布。

对于这个问题,我需要一个并发程序,该程序可以满足Java中的互斥和同步,并提供清晰的解释。谁能帮我吗?

公共汽车

public class Bus {

    public Bus() {
    }

    public void depart() {
        System.out.println("I am departuring from the busstand....");
    }
}

车手

import java.util.ArrayList;
import java.util.concurrent.Semaphore;

public class Rider{

    public void invokeBoard() {
        System.out.println("I am boarding to the .... in the bus");
    }
}

公交车站管理器

import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class BusstandManager {
    boolean isArrived;
    int n;
    Semaphore count_mutex;
    Semaphore bus_mutex;
    ArrayList<Rider> waiting_stage_queue;
    ArrayList<Rider> bus_stand_queue;

    public BusstandManager() {

        this.isArrived = false;
        this.n = 0;
        this.count_mutex = new Semaphore(1);
        this.bus_mutex = new Semaphore(1);
        this.waiting_stage_queue = new ArrayList<>();
        this.bus_stand_queue = new ArrayList<>();
    }

    public void putRider() {
        Rider rider = new Rider();
        try {
            count_mutex.acquire();
            if (n < 50 && !isArrived) {
                n = n + 1;
                bus_stand_queue.add(rider);
            } else {
                waiting_stage_queue.add(rider);
            }
            count_mutex.release();
        } catch (InterruptedException e) {
            System.out.println("Thread is suspended");
        }
    }

    public void load_bus()  {
        try{
        bus_mutex.acquire();
        Bus bus = new Bus();
        isArrived = true;
        if (n != 0) {
            for (Rider rider : bus_stand_queue) {
                rider.invokeBoard();
            }
            n = 0;
        }
        bus.depart();}
        catch (InterruptedException ie){
            System.out.println("Thread is suspended");

        }
    }

    public void execute() {
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        // method reference introduced in Java 8
        executorService.submit(this::putRider);
        executorService.submit(this::load_bus);

        // close executorService
        executorService.shutdown();
    }
}

用法

public class Main {

    public static void main(String[] args) {
        BusstandManager busstandManager = new BusstandManager();
        busstandManager.execute();
    }
}

线程未运行,因为我期望输出

output

解决方法

此问题是并发编程中的常见问题。格兰特·哈钦斯(Grant Hutchins)为这个问题做了出色的解决方案。 他使用了3个信号灯和一个计数器来获取解决方案

waiting = 0;
mutex = new Semaphore(1)
bus = new Semaphore(0)
boarded = new Semaphore(0)

正在等待-登机区的骑手人数。

mutex-用于保护等待变量。

公共汽车-用于告诉骑手是否在法庭上乘坐公共汽车。

已登车-用于告知公交车乘客已登车。

总线过程代码

mutex . wait ()
n = min ( waiting,50)
for i in range ( n ):
bus . signal ()
boarded . wait ()
waiting = max ( waiting -50,0)
mutex . signal ()
depart ()

在这里,互斥锁用于锁定等待变量,因为每当总线到达时,任何人都无法增加等待时间。 n是等待的最小值,是50,因为如果我们有70个车手,那么我们只能让50个车手上车;如果我们有30个车手,那么我们可以让所有车手上车。在此最低条件下,我们仅可乘坐50名乘客。 然后,每辆公共汽车都会发出信号,告知到达者,以便驾驶员可以乘坐公共汽车。

50个车手登上公交车后,如果最初阶段的车手少于50人,则等待时间将设置为零,否则,由于50个车手登车,我们将减少50个车手。

然后我们释放互斥锁,以便新手能够来并增加其价值。

车手代码

mutex . wait ()
waiting += 1
mutex . signal ()
bus . wait ()
board ()
boarded . signal ()

rider线程在获得互斥锁时会等待互斥锁,它将增加等待状态,以告知它正在等待总线。

骑手线程正在等待总线,因此当总线到达总线时,骑手线程可以使用board方法。然后,骑手执行board()方法,这将表明骑手已登机。这样总线将再次发出信号以登上另一个线程。

我们还有另一种解决方案,它在此book中有所描述。 Java实现可在此github link

中找到

`