有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何避免线程耗尽

假设我有一家有m间客房的酒店

客人(线程)总是进进出出

一个房间里可以有很多人,但只有一个房间会有人。例如:

  • 客人A(想要1号房间)
  • 客人B(想要2号房间)
  • 客人C(1号房间)

    一旦所有房间都空了,A可以去1号房间

    B还不能去2号房间,因为还有一个房间里还有人

    C可以去1号房间,因为C想要的房间是里面唯一有人的房间

  • 考虑到A和C离开1号房间,B应该可以去2号房间

  • 最后一位离开房间的客人应该阻止其他客人(避免他们在他出来的时候进来)直到房间离开,这样其他人可以继续

我该如何实现这一点——线程不会饿死

为了简单起见,假设客人一进房间,就睡几秒钟,然后出去。以下是我(错误的)实现:

import java.util.ArrayList;
import java.util.Random;

public class Guest extends Thread {
    static Rooms rooms = new Rooms(5);

    int id;

    Guest(int id) {
        this.id = id;
    }

    public void run() {

        rooms.join(this);

        nap();

        rooms.quit(this);
    }

    public void nap() {
        try {
            sleep((new Random().nextInt(4000) + 1000));
        } catch (InterruptedException e) {
        }
    }

    public static void main(String[] args) throws InterruptedException {

        for (int i = 0; i < 20; i++) {

            Thread t = new Guest(i);
            t.start();

            Thread.sleep((long) new Random().nextInt(1500) + 1000);

        }

    }

}

class Rooms {

    Room[] rooms;
    int busy;

    Rooms(int m) {
        busy = -1;
        rooms = new Room[m + 1];
        for (int i = 0; i < m + 1; i++)
            rooms[i] = new Room();
    }

    void join(Guest h) {
        if (busy == -1) {
            busy = (new Random().nextInt(rooms.length));
        }

        rooms[busy].add(h);

        System.out.println("Guest " + h.id + " came inside room " + busy + " with " + rooms[busy].size() + " people");
    }

    void quit(Guest h) {

        if (rooms[busy].size() == 1) {
            setHandler(busy, h);
        } else {
            rooms[busy].remove(h);
            System.out
                    .println("Guest " + h.id + " came out of room " + busy + " with " + rooms[busy].size() + " people");
        }

    }

    synchronized void setHandler(int numQuarto, Guest ultimo) {
        System.out.println("(Last) Guest " + ultimo.id + " came out of room " + busy + " with "
                + rooms[numQuarto].size() + " people");
        rooms[numQuarto].remove(ultimo);
        busy = -1;
    }

}

class Room extends ArrayList<Guest> {
}

共 (1) 个答案

  1. # 1 楼答案

    你不能。根据你所给予的,需要实施其他机制来保证不会发生饥饿。比如

    Guests (Threads) come in and out the whole time.

    因此,n线程有可能在整个时间内都进入房间m。也有可能,在这段时间里,更多的线程进来想要另一个房间。但是,在房间m首次清空之前,他们无法进入房间(这可能永远不会发生)。这可以在任意数量的房间和线程中继续。即使

    For simplicity, suppose that, once the Guest comes inside a room, it sleeps for some seconds and then get out.

    那是因为

    C can go to Room 1, because the Room C wants is the only Room with people inside;

    这意味着另一个线程可能进入一个已经被占用的房间,其中一个或多个线程还有t时间睡觉。新线程进入睡眠状态,直到上一个线程之后才会醒来。睡觉时,可能会有更多线程进入该房间,这可能会导致其他线程等待其他房间饿死