Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使线程在不阻塞其他线程的情况下等待某个事件发生_Java_Multithreading_Wait_Notify - Fatal编程技术网

Java 如何使线程在不阻塞其他线程的情况下等待某个事件发生

Java 如何使线程在不阻塞其他线程的情况下等待某个事件发生,java,multithreading,wait,notify,Java,Multithreading,Wait,Notify,我正在用java中的线程进行理发店模拟。理发店由一个带n把椅子的等候室和一个带几把理发椅的理发室组成。如果没有顾客,理发师就睡觉。如果顾客进入理发店,所有的椅子都被占满了,那么顾客就离开了理发店。如果理发师很忙,但椅子有空,那么顾客就坐在其中一张空椅子上。如果理发师睡着了,顾客就会叫醒理发师 到目前为止,我的代码运行良好(我认为),但有一个错误。在这里,客户在随机数毫秒后前往理发店,并且可以多次前往理发店。问题是,如果客户已经在理发店,在服务完成之前,它不能再去那里,这意味着,我需要阻止客户的线

我正在用java中的线程进行理发店模拟。理发店由一个带n把椅子的等候室和一个带几把理发椅的理发室组成。如果没有顾客,理发师就睡觉。如果顾客进入理发店,所有的椅子都被占满了,那么顾客就离开了理发店。如果理发师很忙,但椅子有空,那么顾客就坐在其中一张空椅子上。如果理发师睡着了,顾客就会叫醒理发师

到目前为止,我的代码运行良好(我认为),但有一个错误。在这里,客户在随机数毫秒后前往理发店,并且可以多次前往理发店。问题是,如果客户已经在理发店,在服务完成之前,它不能再去那里,这意味着,我需要阻止客户的线程,直到理发师完成理发,这就是我的代码失败的地方。我很确定这必须用wait()和notify()来完成,但是当我这样做的时候,我把其余的线程搞乱了,可能是我做错了什么。那么我如何同步呢?提前感谢:)

这是我的密码:

Main.java:

public class Main {

public static int tiempoSimulacion;

public static Logger logger = Logger.getLogger("ccia.labarberia");
static {
    logger.setLevel(Level.OFF)
    //logger.setLevel(Level.WARNING)
    ;}

public static void main(String[] args) throws InterruptedException {
    Scanner sc = new Scanner(System.in);

    int nBarberos = sc.nextInt();
    int nClientes = sc.nextInt();
    tiempoSimulacion = sc.nextInt();

    Cliente.distribucionNormal = new NormalDistribution(sc.nextInt(),sc.nextInt());

    Barbero.distribucionExponencial = new ExponentialDistribution(sc.nextInt());

    Barberia b = Barberia.getBarberia(); // La Barberia sigue el patrón Singleton

    Cliente.barberia = b;
    Barbero.barberia = b;
    b.setNumeroSillas(sc.nextInt());
    sc.close();

    Barbero[] barberos = new Barbero[nBarberos];
    for (int i=1; i<=nBarberos; i++){
        barberos[i-1] = new Barbero(i);
        barberos[i-1].start();
    }
    b.setBarberos(barberos);

    Thread[] clientes = new Thread[nClientes];
    for (int j=1; j<=nClientes; j++){
        clientes[j-1] = new Thread(new Cliente(j));
        clientes[j-1].start();
    }

    Thread.sleep(tiempoSimulacion*1000);

    for (int j=0; j<nClientes; j++){
        clientes[j].interrupt();
    }

    for (int i=0; i<nBarberos; i++){
        barberos[i].interrupt();
    }

    for (int j=0; j<nClientes; j++){
        clientes[j].join();
    }

    for (int i=0; i<nBarberos; i++){
        barberos[i].join();
    }


}

}
Barber.java:

public class Barbero extends Thread{

private static final int OFFSET = 64;
public static Barberia barberia;
public static ExponentialDistribution distribucionExponencial;
private char id;

public Barbero(int i) {
    this.id = (char) (OFFSET + i); 
    System.out.println("El barbero " + this.id + " se ha creado.");
}

public char identificador() {
    return this.id;
}

@Override
public void run() {
    try {
        while(!Thread.interrupted()) {
            barberia.cortarPelo(this);  
        } 
    } catch (InterruptedException ex) {
        System.out.println("El barbero " + this.id + " ha sido destruido.");
    }

}
}
Barbershop.java:

public class Barberia {

private static Barberia mBarberia;
private static int numSillas;
private Barbero[] barberos;
LinkedList<Cliente> listaClientes;

protected Barberia() {
    listaClientes = new LinkedList<Cliente>();
}

public static Barberia getBarberia() {
    if (mBarberia == null) {
        mBarberia = new Barberia();
    }
    return mBarberia;
}

public void setNumeroSillas(int sillas) {
    numSillas = sillas;
}

public void setBarberos(Barbero[] b) {
    this.barberos = new Barbero[b.length];
    for (int i=0; i<this.barberos.length; i++) {
        this.barberos[i] = b[i];
    }
}

public void cortarPelo(Barbero barbero) throws InterruptedException{

    Cliente cliente;
    synchronized (listaClientes) {
        while(listaClientes.size()==0) {
            System.out.println("El barbero " + barbero.identificador() + " se pone a dormir.");
            listaClientes.wait();
        }
        cliente = listaClientes.poll();

    }    
    System.out.println("El barbero " + barbero.identificador() + " atiende al cliente " + cliente.identificador() + ".");
    Thread.sleep((long)Barbero.distribucionExponencial.sample() );
    System.out.println("El barbero " + barbero.identificador() + " ha cortado el pelo al cliente " + cliente.identificador() + ".");

}

public void add (Cliente cliente) throws InterruptedException{
     System.out.println("El cliente " + cliente.identificador() + " llega a la barbería.");
     synchronized (listaClientes) {
         if(listaClientes.size() == numSillas) {
             System.out.println("El cliente " + cliente.identificador() + " se marcha sin ser atendido."); 
         } else {
             listaClientes.offer(cliente);

             if(listaClientes.size()>0 && listaClientes.size() <= barberos.length){
                 listaClientes.notify();
             } else {
                 System.out.println("El cliente " + cliente.identificador() + " se sienta en una silla de espera.");
             }  
         }    
     }
}
}
公共类Barberia{
私人静态巴贝拉;
私有静态int numSillas;
私人巴贝罗[]巴贝罗;
LinkedList ListaClient;
受保护的巴伯里亚(){
listaClientes=newlinkedlist();
}
公共静态Barberia getBarberia(){
如果(mBarberia==null){
姆巴贝里亚=新巴贝里亚();
}
返回姆巴贝里亚;
}
公共空间集合数字(国际新罗){
numSillas=sillas;
}
公共空间(巴贝罗[]b){
this.barberos=新的Barbero[b.length];

对于(int i=0;i0&&listaClientes.size()您想要实现的目标,可以通过使用同步功能来实现。当多个线程同步同一对象时,java会自然处理您寻求的行为:

  • 一次只能有一个线程访问同步锁 其他人等待
  • 当锁空闲时,所有等待的线程都会尝试访问它。无需使用wait、join或notify

    下面是一个例子,实现了您提到的行为:几个客户试图同时访问理发店的同一个座位

理发店和主要项目:

public class BarberShop
{

// The main programm
public static void main(final String[] args)
{
    // creating a Barbershopand its clients
    final BarberShop shop = new BarberShop();
    final BarberClient c1 = new BarberClient(shop, "Ian", 5);

    final BarberClient c2 = new BarberClient(shop, "Chewy", 10);

    final BarberClient c3 = new BarberClient(shop, "Luke", 3);

    // all clients Try to go to the barbershop concurrently
    c1.launchGoToBarberThread();
    c2.launchGoToBarberThread();
    c3.launchGoToBarberThread();

    // Example output :
    // Chewy Waiting for barbershop
    // Luke Waiting for barbershop
    // Ian Waiting for barbershop
    // Chewy Entered Barber shop at Fri Nov 27 14:32:38 CET 2015
    // Chewy Exiting Barber shop at Fri Nov 27 14:32:43 CET 2015
    // Ian Entered Barber shop at Fri Nov 27 14:32:43 CET 2015
    // Ian Exiting Barber shop at Fri Nov 27 14:32:45 CET 2015
    // Luke Entered Barber shop at Fri Nov 27 14:32:45 CET 2015
    // Luke Exiting Barber shop at Fri Nov 27 14:32:47 CET 2015

}
}
在商店中同步的客户端:

import java.util.Date;

// client class implementing the concurrency behaviour around the seat.
public class BarberClient
{

// the shop we synchronize on. Let's say it has only one seat and we synchronize on this.
private final BarberShop barberShop;

private final String     name;      // a name

private final int        beardSize; // the size of the beard to represent the time in the seat

private final Thread     thread;    // the thread that will actually be launched.

// constructor with name and beard size.
public BarberClient(final BarberShop pBarberShop,
                    final String pName,
                    final int pBeardSize)
{
    barberShop = pBarberShop;
    name = pName;
    beardSize = pBeardSize;

    // create the thread that just try to go to the barber...
    thread = new Thread(new Runnable()
    {
        @Override
        public void run()
        {
            try
            {
                goToBarber();

            } catch (final InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    });
}

// method concurrently trting to go to the shop
private void goToBarber() throws InterruptedException
{
    System.out.println(name + "\tWaiting for barbershop");// display client is waiting

    // Synchronize on the shop. It means you can seat only if nobody is on the seat. And waits for the seat
    // being free.
    synchronized (barberShop)
    {
        // We entered the synchronization block (= accessed to the seat).
        // NOBODY else can access the seat while we are here.

        // log enter, exit time, and wait for some time for the barber to do his job...
        System.out.println(name + "\tEntered Barber shop at " + new Date(System.currentTimeMillis()));
        Thread.sleep(500 * beardSize);
        System.out.println(name + "\tExiting Barber shop at " + new Date(System.currentTimeMillis()));
    }
    // now we have leave the synchronization block (and the seat). Anybody can go.
}

// method to launch the thread.
public void launchGoToBarberThread()
{
    thread.start();
}
}
我希望它能帮助你实现你的行为。
这里有一些关于同步的信息:

为什么不使用join?
wait()
notify())是低级的原始操作,使用起来很复杂。考虑使用更高级的同步对象来代替。阻塞队列可以是多用途的。例如,您可以让客户等待通过从代码到()的权限从椅子上站起来。
队列中的令牌。然后barber线程可以通过put()向客户端授予权限将任何对象放入队列。否,
synchronized
语句的目的是防止两个或多个线程同时访问相同的数据。如果希望一个线程等待另一个线程执行某项操作,则可以使用低级原语
o.wait()
o.notify()/o.notifyAll()
,但最好使用
java.util.concurrent
包中定义的一个更高级别的同步对象(队列、信号量、屏障等)。
import java.util.Date;

// client class implementing the concurrency behaviour around the seat.
public class BarberClient
{

// the shop we synchronize on. Let's say it has only one seat and we synchronize on this.
private final BarberShop barberShop;

private final String     name;      // a name

private final int        beardSize; // the size of the beard to represent the time in the seat

private final Thread     thread;    // the thread that will actually be launched.

// constructor with name and beard size.
public BarberClient(final BarberShop pBarberShop,
                    final String pName,
                    final int pBeardSize)
{
    barberShop = pBarberShop;
    name = pName;
    beardSize = pBeardSize;

    // create the thread that just try to go to the barber...
    thread = new Thread(new Runnable()
    {
        @Override
        public void run()
        {
            try
            {
                goToBarber();

            } catch (final InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    });
}

// method concurrently trting to go to the shop
private void goToBarber() throws InterruptedException
{
    System.out.println(name + "\tWaiting for barbershop");// display client is waiting

    // Synchronize on the shop. It means you can seat only if nobody is on the seat. And waits for the seat
    // being free.
    synchronized (barberShop)
    {
        // We entered the synchronization block (= accessed to the seat).
        // NOBODY else can access the seat while we are here.

        // log enter, exit time, and wait for some time for the barber to do his job...
        System.out.println(name + "\tEntered Barber shop at " + new Date(System.currentTimeMillis()));
        Thread.sleep(500 * beardSize);
        System.out.println(name + "\tExiting Barber shop at " + new Date(System.currentTimeMillis()));
    }
    // now we have leave the synchronization block (and the seat). Anybody can go.
}

// method to launch the thread.
public void launchGoToBarberThread()
{
    thread.start();
}
}