简体   繁体   English

Java-两个具有wait()和notify()的线程

[英]Java - two threads with wait() and notify()

I am new to Java programming. 我是Java编程的新手。 i want to run two threads using wait() and notify(). 我想使用wait()和notify()运行两个线程。 But I cant use task flags for thread synchronization,sleep, yield or wait(parameter).I wrote it, but i had to use sleep. 但是我不能使用任务标记来进行线程同步,睡眠,屈服或等待(参数)。我写了它,但是我不得不使用睡眠。 can someone help me to change it to without sleep. 有人可以帮助我将其更改为不睡觉。 This is my main class 这是我的主班

public class mainClass{

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

           final Processor processor = new Processor();

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

               final int z = i;
               Thread trainer = new Thread(new Runnable(){

                   public void run(){
                       try{
                           processor.produce(z);
                       }catch(InterruptedException e){
                           e.printStackTrace();
                       }
                   }           
               });

               Thread sportsman = new Thread(new Runnable(){

                   public void run(){
                       try{
                           processor.consume(z);
                       }catch(InterruptedException e){
                           e.printStackTrace();
                       }
                   }           
               });

               trainer.start();
               sportsman.start();

               trainer.join();
               sportsman.join();

           }
           System.out.println("100 Tasks are Finished.");
       }          
    }

this is my second class. 这是我的第二堂课。

public class Processor {

public void produce(int n) throws InterruptedException {
    synchronized (this){
        System.out.println("Trainer making " + (n+1) + " Task..." );
        wait();
        System.out.println(""); 
    }
}

public void consume(int m) throws InterruptedException {
    Thread.sleep(1); 
    //I want to run the code without using sleep and get same output
    synchronized (this){
        System.out.println("Sportman doing " + (m+1) + " Task...");
        notify();
    }
}
}

this is my output. 这是我的输出。

Trainer making 1 Task...
Sportman doing 1 Task...

Trainer making 2 Task...
Sportman doing 2 Task...

.
.
.

Trainer making 99 Task...
Sportman doing 99 Task...

Trainer making 100 Task...
Sportman doing 100 Task...

100 Tasks are Finished.

thank you. 谢谢。 my english is bad. 我的英语不好。 sorry for it. 对不起

Hints: 提示:

  1. The correct use of wait involves waiting for something specific to happen. wait的正确用法包括等待特定的事件发生。 The correct implementation is something like this 正确的实现是这样的

     synchronize (x) { while (!x.itHasHappened()) { x.wait(); // for it to happen } } 

    The loop is necessary since it is possible to get spurious notifies on a primitive lock. 循环是必需的,因为有可能在原始锁上收到虚假通知。

  2. In your specific example, ask yourself what must wait for what to happen. 在您的特定示例中,问自己必须等待什么发生。 I think you've got it wrong. 我想你错了。 What is produce(N) actually waiting for, and why? 什么是produce(N)实际等待,为什么?

In mainClass you created 100 times two threads, I think you should create two threads only and in those two threads run the loop 100 times. 在mainClass中,您创建了两个线程100倍,我认为您应该只创建两个线程,并且在这两个线程中运行100次循环。

Probably you needed to do something like this... 可能您需要做这样的事情...

  1. The producer should create together 100 task (one at a time) and wait after each task for the consumer to be done. 生产者应共同创建100个任务(一次创建一个),并在每个任务完成后等待消费者完成。
  2. The consumer should wait for a task and notify the producer when finished with the current task, them wait for the next task. 消费者应等待任务,并在完成当前任务后通知生产者,他们等待下一个任务。

So your mainClass should look like this, loops should be in the producer() and consumer() methods. 因此,您的mainClass应该看起来像这样,循环应该在producer()和Consumer()方法中。

public class mainClass {

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

    final Processor processor = new Processor();

    Thread trainer = new Thread(new Runnable() {
        public void run() {
            try {
                processor.produce();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });

    Thread sportsman = new Thread(new Runnable() {
        public void run() {
            try {
                processor.consume();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });

    trainer.start();
    sportsman.start();

    trainer.join();
    sportsman.join();

    System.out.println("100 Tasks are Finished."); 
}

}

And the Processor maybe something like this... 处理器也许像这样...

public class Processor {

private int taskNo = 0; // the number of the current task
                        // (0 = there is no task, but will be)
                        // (-1 = there won't be more task)

public void produce() throws InterruptedException {
    synchronized (this) {
        for (int i = 0; i < 100; i++) {
            taskNo = i + 1; // making a task number (i+1)
            System.out.println("Trainer making " + taskNo + " Task...");
            notify(); // notifies the consumer that the task was made
            wait(); // and waiting the consumer to finish... zzzz...
            System.out.println("");
        }
        taskNo = -1; // there will be no more task
        notify(); // notify the consumer about it
    }
}

public void consume() throws InterruptedException {
    synchronized (this) {
        do {
            if (taskNo == 0) {
                wait(); // there is no task to do, waiting... zzzz...
            }
            if (taskNo != -1) {
                System.out.println("Sportman doing " + taskNo + " Task...");
                taskNo = 0; // sets the task to done
                notify(); // notifies the producer that the task was done
            }
        } while (taskNo != -1);
    }
}
}

Typically there is a queue instead of the taskNo variable, where the producer puts tasks and the consumer takes tasks from in. But in your case the queue can have only 1 task at a time, because the producer should wait for the consumer to finish. 通常,有一个队列而不是taskNo变量,生产者在其中放置任务,而使用者从中取出任务。但是在您的情况下,队列一次只能有1个任务,因为生产者应等待使用者完成。 So you can use a simple variable (taskNo) instead of a queue. 因此,您可以使用简单变量(taskNo)代替队列。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM