我能得到一个完整的简单场景,即教程,建议这应该如何使用,特别是与队列?


当前回答

该问题要求wait() + notify()涉及队列(缓冲区)。首先想到的是使用缓冲区的生产者-消费者场景。

我们的系统有三个组成部分:

Queue [Buffer] -线程间共享的固定大小的队列 生成器——线程生成/插入值到缓冲区 消费者——线程从缓冲区中消费/删除值

生产者线程: 生产者在缓冲区中插入值,直到缓冲区满为止。 如果缓冲区已满,生产者调用wait()并进入等待阶段,直到消费者唤醒它。

    static class Producer extends Thread {
    private Queue<Integer> queue;
    private int maxSize;

    public Producer(Queue<Integer> queue, int maxSize, String name) {
        super(name);
        this.queue = queue;
        this.maxSize = maxSize;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (queue) {
                if (queue.size() == maxSize) {
                    try {
                        System.out.println("Queue is full, " + "Producer thread waiting for " + "consumer to take something from queue");
                        queue.wait();
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
                Random random = new Random();
                int i = random.nextInt();
                System.out.println(" ^^^ Producing value : " + i);
                queue.add(i);
                queue.notify();
            }
            sleepRandom();
        }
    }
}

消费者线程: 消费者线程从缓冲区中删除值,直到缓冲区为空。 如果缓冲区为空,消费者调用wait()方法并进入等待状态,直到生产者发送通知信号。

    static class Consumer extends Thread {
    private Queue<Integer> queue;
    private int maxSize;

    public Consumer(Queue<Integer> queue, int maxSize, String name) {
        super(name);
        this.queue = queue;
        this.maxSize = maxSize;
    }

    @Override
    public void run() {
        Random random = new Random();
        while (true) {
            synchronized (queue) {
                if (queue.isEmpty()) {
                    System.out.println("Queue is empty," + "Consumer thread is waiting" + " for producer thread to put something in queue");
                    try {
                        queue.wait();
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
                System.out.println(" vvv Consuming value : " + queue.remove());
                queue.notify();
            }
            sleepRandom();
        }
    }
}

实效的方法:

    public static void sleepRandom(){
    Random random = new Random();
    try {
        Thread.sleep(random.nextInt(250));
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

应用程序代码:

    public static void main(String args[]) {
    System.out.println("How to use wait and notify method in Java");
    System.out.println("Solving Producer Consumper Problem");
    Queue<Integer> buffer = new LinkedList<>();
    int maxSize = 10;
    Thread producer = new Producer(buffer, maxSize, "PRODUCER");
    Thread consumer = new Consumer(buffer, maxSize, "CONSUMER");
    producer.start();
    consumer.start();
}

示例输出:

 ^^^ Producing value : 1268801606
 vvv Consuming value : 1268801606
Queue is empty,Consumer thread is waiting for producer thread to put something in queue
 ^^^ Producing value : -191710046
 vvv Consuming value : -191710046
 ^^^ Producing value : -1096119803
 vvv Consuming value : -1096119803
 ^^^ Producing value : -1502054254
 vvv Consuming value : -1502054254
Queue is empty,Consumer thread is waiting for producer thread to put something in queue
 ^^^ Producing value : 408960851
 vvv Consuming value : 408960851
 ^^^ Producing value : 2140469519
 vvv Consuming value : 65361724
 ^^^ Producing value : 1844915867
 ^^^ Producing value : 1551384069
 ^^^ Producing value : -2112162412
 vvv Consuming value : -887946831
 vvv Consuming value : 1427122528
 ^^^ Producing value : -181736500
 ^^^ Producing value : -1603239584
 ^^^ Producing value : 175404355
 vvv Consuming value : 1356483172
 ^^^ Producing value : -1505603127
 vvv Consuming value : 267333829
 ^^^ Producing value : 1986055041
Queue is full, Producer thread waiting for consumer to take something from queue
 vvv Consuming value : -1289385327
 ^^^ Producing value : 58340504
 vvv Consuming value : 1244183136
 ^^^ Producing value : 1582191907
Queue is full, Producer thread waiting for consumer to take something from queue
 vvv Consuming value : 1401174346
 ^^^ Producing value : 1617821198
 vvv Consuming value : -1827889861
 vvv Consuming value : 2098088641

其他回答

你看过这个Java教程吗?

此外,我建议您在真正的软件中远离这类东西。使用它很好,这样您就知道它是什么,但是并发性到处都有陷阱。如果您正在为其他人构建软件,最好使用更高级别的抽象和同步集合或JMS队列。

至少我是这么做的。我不是并发专家,所以我尽量避免手工处理线程。

即使你特别要求wait()和notify(),我觉得这句话仍然足够重要:

Josh Bloch, Effective Java第二版,第69项:更喜欢并发实用程序来等待和通知(强调他的):

考虑到正确使用等待和通知的困难,您应该使用更高级别的并发实用程序[…]与java.util.concurrent提供的高级语言相比,直接使用wait和notify就像用“并发汇编语言”编程。很少有理由在新代码中使用wait和notify。

线程中wait()和notifyall()的例子。

一个同步的静态数组列表被用作资源,如果数组列表为空,则调用wait()方法。一旦为数组列表添加了元素,就调用Notify()方法。

public class PrinterResource extends Thread{

//resource
public static List<String> arrayList = new ArrayList<String>();

public void addElement(String a){
    //System.out.println("Add element method "+this.getName());
    synchronized (arrayList) {
        arrayList.add(a);
        arrayList.notifyAll();
    }
}

public void removeElement(){
    //System.out.println("Remove element method  "+this.getName());
    synchronized (arrayList) {
        if(arrayList.size() == 0){
            try {
                arrayList.wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }else{
            arrayList.remove(0);
        }
    }
}

public void run(){
    System.out.println("Thread name -- "+this.getName());
    if(!this.getName().equalsIgnoreCase("p4")){
        this.removeElement();
    }
    this.addElement("threads");

}

public static void main(String[] args) {
    PrinterResource p1 = new PrinterResource();
    p1.setName("p1");
    p1.start();

    PrinterResource p2 = new PrinterResource();
    p2.setName("p2");
    p2.start();


    PrinterResource p3 = new PrinterResource();
    p3.setName("p3");
    p3.start();


    PrinterResource p4 = new PrinterResource();
    p4.setName("p4");
    p4.start();     

    try{
        p1.join();
        p2.join();
        p3.join();
        p4.join();
    }catch(InterruptedException e){
        e.printStackTrace();
    }
    System.out.println("Final size of arraylist  "+arrayList.size());
   }
}

该问题要求wait() + notify()涉及队列(缓冲区)。首先想到的是使用缓冲区的生产者-消费者场景。

我们的系统有三个组成部分:

Queue [Buffer] -线程间共享的固定大小的队列 生成器——线程生成/插入值到缓冲区 消费者——线程从缓冲区中消费/删除值

生产者线程: 生产者在缓冲区中插入值,直到缓冲区满为止。 如果缓冲区已满,生产者调用wait()并进入等待阶段,直到消费者唤醒它。

    static class Producer extends Thread {
    private Queue<Integer> queue;
    private int maxSize;

    public Producer(Queue<Integer> queue, int maxSize, String name) {
        super(name);
        this.queue = queue;
        this.maxSize = maxSize;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (queue) {
                if (queue.size() == maxSize) {
                    try {
                        System.out.println("Queue is full, " + "Producer thread waiting for " + "consumer to take something from queue");
                        queue.wait();
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
                Random random = new Random();
                int i = random.nextInt();
                System.out.println(" ^^^ Producing value : " + i);
                queue.add(i);
                queue.notify();
            }
            sleepRandom();
        }
    }
}

消费者线程: 消费者线程从缓冲区中删除值,直到缓冲区为空。 如果缓冲区为空,消费者调用wait()方法并进入等待状态,直到生产者发送通知信号。

    static class Consumer extends Thread {
    private Queue<Integer> queue;
    private int maxSize;

    public Consumer(Queue<Integer> queue, int maxSize, String name) {
        super(name);
        this.queue = queue;
        this.maxSize = maxSize;
    }

    @Override
    public void run() {
        Random random = new Random();
        while (true) {
            synchronized (queue) {
                if (queue.isEmpty()) {
                    System.out.println("Queue is empty," + "Consumer thread is waiting" + " for producer thread to put something in queue");
                    try {
                        queue.wait();
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
                System.out.println(" vvv Consuming value : " + queue.remove());
                queue.notify();
            }
            sleepRandom();
        }
    }
}

实效的方法:

    public static void sleepRandom(){
    Random random = new Random();
    try {
        Thread.sleep(random.nextInt(250));
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

应用程序代码:

    public static void main(String args[]) {
    System.out.println("How to use wait and notify method in Java");
    System.out.println("Solving Producer Consumper Problem");
    Queue<Integer> buffer = new LinkedList<>();
    int maxSize = 10;
    Thread producer = new Producer(buffer, maxSize, "PRODUCER");
    Thread consumer = new Consumer(buffer, maxSize, "CONSUMER");
    producer.start();
    consumer.start();
}

示例输出:

 ^^^ Producing value : 1268801606
 vvv Consuming value : 1268801606
Queue is empty,Consumer thread is waiting for producer thread to put something in queue
 ^^^ Producing value : -191710046
 vvv Consuming value : -191710046
 ^^^ Producing value : -1096119803
 vvv Consuming value : -1096119803
 ^^^ Producing value : -1502054254
 vvv Consuming value : -1502054254
Queue is empty,Consumer thread is waiting for producer thread to put something in queue
 ^^^ Producing value : 408960851
 vvv Consuming value : 408960851
 ^^^ Producing value : 2140469519
 vvv Consuming value : 65361724
 ^^^ Producing value : 1844915867
 ^^^ Producing value : 1551384069
 ^^^ Producing value : -2112162412
 vvv Consuming value : -887946831
 vvv Consuming value : 1427122528
 ^^^ Producing value : -181736500
 ^^^ Producing value : -1603239584
 ^^^ Producing value : 175404355
 vvv Consuming value : 1356483172
 ^^^ Producing value : -1505603127
 vvv Consuming value : 267333829
 ^^^ Producing value : 1986055041
Queue is full, Producer thread waiting for consumer to take something from queue
 vvv Consuming value : -1289385327
 ^^^ Producing value : 58340504
 vvv Consuming value : 1244183136
 ^^^ Producing value : 1582191907
Queue is full, Producer thread waiting for consumer to take something from queue
 vvv Consuming value : 1401174346
 ^^^ Producing value : 1617821198
 vvv Consuming value : -1827889861
 vvv Consuming value : 2098088641

例子

public class myThread extends Thread{
     @override
     public void run(){
        while(true){
           threadCondWait();// Circle waiting...
           //bla bla bla bla
        }
     }
     public synchronized void threadCondWait(){
        while(myCondition){
           wait();//Comminucate with notify()
        }
     }

}
public class myAnotherThread extends Thread{
     @override
     public void run(){
        //Bla Bla bla
        notify();//Trigger wait() Next Step
     }

}