Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.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 - Fatal编程技术网

Java 如何使两个线程等待并相互通知

Java 如何使两个线程等待并相互通知,java,multithreading,Java,Multithreading,我必须创建两个线程,这两个线程必须在2秒钟的时间间隔内从队列中轮询和对象 第一个线程轮询对象,然后等待并通知第二个线程轮询其队列中的对象 我读了所有关于等待和通知的书,但都不适合我 有什么建议吗 第一个线程: public class SouthThread extends Thread { private Queue<Car> q = new LinkedList<Car>(); public void CreateQueue() { Scanner in

我必须创建两个线程,这两个线程必须在2秒钟的时间间隔内从队列中轮询和对象

第一个线程轮询对象,然后等待并通知第二个线程轮询其队列中的对象

我读了所有关于等待和通知的书,但都不适合我

有什么建议吗

第一个线程:

public class SouthThread extends Thread {

private Queue<Car> q = new LinkedList<Car>();

public void CreateQueue() {

    Scanner input = new Scanner(System.in);

    for (int i = 0; i < 2; i++) {
        Car c = new Car();
        System.out.println("Enter registration number: ");
        String regNum = input.nextLine();
        c.setRegNum(regNum);
        q.offer(c);
    }
}

public int getQueueSize() {
    return q.size();
}

@Override
public void run() {
    while (q.size() != 0)
        try {
            while (q.size() != 0) {
                synchronized (this) {
                    System.out.print("The car with registration number: ");
                    System.out.print(q.poll().getRegNum());
                    System.out
                            .println(" have passed the bridge from the south side.");
                    this.wait(2000);
                    notify();

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

}
wait
notify
必须引用同一个锁:当你调用
对象时。wait(2000)
你说的是“我将在这里等待2000毫秒,或者直到其他人调用
对象。notify()
对象
指我的地方”


我仍然不完全理解您想要实现什么,但是如果您只是想要两个线程同时执行以下操作:

  • 做点什么
  • 等2秒钟
  • 转到1
  • 然后,您根本不需要等待/通知,您可以使用
    Thread.sleep()
    java.util.Timer
    的两个实例


    但是,我不确定我是否理解正确-(

    似乎您基本上想要实现的是一个系统,它在两个独立的单元之间交替控制,以便每个单元都有一段时间来处理,然后是两秒钟的等待期(反之亦然)

    有两种主要方法可以实现这一点:

  • 使用中央控制
  • 使用自主通信代理
  • 第一种方法比较简单。这里有一个中央“主”组件,负责协调谁获得处理时间,并实现等待时间。对于这种方法,两个独立的单元甚至不必是线程:

    public class-South{
    private Queue q=new LinkedList();
    public void CreateQueue(){…}
    公众投票{
    系统输出打印(“登记号为:”)的汽车;
    System.out.print(q.poll().getRegNum());
    System.out.println(“已经从南侧通过了桥”);
    }
    }
    公共舱北{
    private Queue q=new LinkedList();
    public void CreateQueue(){…}
    公众投票{
    系统输出打印(“登记号为:”)的汽车;
    System.out.print(q.poll().getRegNum());
    System.out.println(“从北侧通过了桥”);
    }
    }
    //这是“大师”班
    公共班机{
    公共静态void main(字符串[]args){
    南南=新南();
    北北=新北();
    south.CreateQueue();
    CreateQueue();
    布尔完成=假;
    而(!完成){
    试一试{
    《睡眠》(2000年);
    }(捕获中断异常){/*TODO*/}
    north.poll();
    试一试{
    《睡眠》(2000年);
    }(捕获中断异常){/*TODO*/}
    south.poll();
    }
    }
    }
    
    请注意,这里的North和South并不继承自
    线程
    ,也就是说,它们只是普通的旧对象。 (但是,如果您的程序更复杂,并且南北方向只是其中的一部分,那么您可能希望将Main(!)作为一个单独的线程,并将上面的while循环放在线程的
    run
    方法中,以便程序的其余部分可以同时运行。)

    在第二种方法中,您没有这样的中央控制组件,但是北方和南方都在各自独立的线程中运行。这就要求它们通过相互通信来协调允许谁进行处理

    公共类SouthThread扩展线程{
    受保护队列q=新的LinkedList();
    受保护的北方;
    public void CreateQueue(){…}
    public void poll(){…}
    公开募捐{
    布尔完成=假;
    而(!完成){
    //等两秒钟
    试一试{
    《睡眠》(2000年);
    }(捕获中断异常){/*TODO*/}
    //处理队列中的一个元素
    poll();
    //通知另一个线程
    同步(北){
    north.notifyAll();
    }
    //等待另一个线程通知这个线程
    试一试{
    已同步(此){
    等待();
    }
    }(捕获中断异常){/*TODO*/}
    }
    }
    }
    公共类NorthThread扩展线程{
    受保护队列q=新的LinkedList();
    南南保护;
    public void CreateQueue(){…}
    public void poll(){…}
    公开募捐{
    布尔完成=假;
    而(!完成){
    //等两秒钟
    试一试{
    《睡眠》(2000年);
    }(捕获中断异常){/*TODO*/}
    //处理队列中的一个元素
    poll();
    //通知另一个线程
    (南部){
    south.notifyAll();
    }
    //等待另一个线程通知这个线程
    试一试{
    已同步(此){
    等待();
    }
    }(捕获中断异常){/*TODO*/}
    }
    }
    }
    公共班机{
    公共静态void main(字符串[]args)引发异常{
    SouthThread tSouthThread=新的SouthThread();
    NorthThread tNorthThread=新的NorthThread();
    tSouthThread.north=tnothread;
    tnothread.south=tSouthThread;
    tSouthThread.CreateQueue();
    tNorthThread.CreateQueue();
    tSouthThread.start();
    tnothread.start();
    }
    }
    
    更一般的一句话:由于北方和南方的做法似乎基本相同,因此可能不需要在两个单独的类中实现它们。相反,只有一个类实现所需的功能并实例化两次就足够了:

    //我们可以将North和Sout的功能结合起来
    
    public class NorthThread extends Thread {
    private Queue<Car> q = new LinkedList<Car>();
    
    public void CreateQueue() {
    
        Scanner input = new Scanner(System.in);
    
        for (int i = 0; i < 2; i++) {
            Car c = new Car();
            System.out.println("Enter registration number: ");
            String regNum = input.nextLine();
            c.setRegNum(regNum);
            q.offer(c);
        }
    }
    
    public int getQueueSize() {
        return q.size();
    }
    
    @Override
    public void run() {
        try {
            while (q.size() != 0) {
                synchronized (this) {
                    System.out.print("The car with registration number: ");
                    System.out.print(q.poll().getRegNum());
                    System.out
                            .println(" have passed the bridge from the north side.");
                    this.wait(2000);
                    notify();
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    
    }
    
    public class Main {
    
    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
    
        SouthThread tSouthThread = new SouthThread();
        NorthThread tNorthThread = new NorthThread();
    
        tSouthThread.CreateQueue();
        tNorthThread.CreateQueue();
    
        System.out.println(tSouthThread.getQueueSize());
    
        tSouthThread.start();
        tNorthThread.start();
    
    
    }