java中使用wait()和notify()的简单场景

发布于 2024-08-26 12:46:05 字数 42 浏览 7 评论 0原文

我可以获得一个完整的简单场景,即建议如何使用它的教程,特别是使用队列?

Can I get a complete simple scenario i.e. tutorial that suggest how this should be used, specifically with a Queue?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

久伴你 2024-09-02 12:46:05

wait()notify() 方法旨在提供一种机制,允许线程阻塞直到满足特定条件。为此,我假设您想要编写一个阻塞队列实现,其中有一些固定大小的元素后备存储。

您要做的第一件事是确定您希望方法等待的条件。在这种情况下,您将希望 put() 方法阻塞,直到存储中有可用空间,并且您将希望 take() 方法阻塞,直到有可用空间。是一些要返回的元素。

public class BlockingQueue<T> {

    private Queue<T> queue = new LinkedList<T>();
    private int capacity;

    public BlockingQueue(int capacity) {
        this.capacity = capacity;
    }

    public synchronized void put(T element) throws InterruptedException {
        while(queue.size() == capacity) {
            wait();
        }

        queue.add(element);
        notify(); // notifyAll() for multiple producer/consumer threads
    }

    public synchronized T take() throws InterruptedException {
        while(queue.isEmpty()) {
            wait();
        }

        T item = queue.remove();
        notify(); // notifyAll() for multiple producer/consumer threads
        return item;
    }
}

关于使用等待和通知机制的方式,有几点需要注意。

首先,您需要确保对 wait()notify() 的任何调用都位于代码的同步区域内(使用 wait() > 和 notify() 调用在同一对象上同步)。造成这种情况的原因(除了标准线程安全问题之外)是由于丢失信号造成的。

一个例子是,当队列碰巧已满时,线程可能会调用 put() ,然后它会检查条件,发现队列已满,但是在它可以阻止另一个线程之前已安排。然后,第二个线程从队列中 take() 获取一个元素,并通知等待线程队列已满。然而,因为第一个线程已经检查了条件,所以即使它可以取得进展,它也会在重新调度后简单地调用 wait()

通过同步共享对象,您可以确保不会发生此问题,因为在第一个线程实际阻塞之前,第二个线程的 take() 调用将无法取得进展。

其次,由于存在称为虚假唤醒的问题,您需要将要检查的条件放入 while 循环中,而不是 if 语句中。有时可以在不调用 notify() 的情况下重新激活等待线程。将此检查放入 while 循环中将确保如果发生虚假唤醒,将重新检查条件,并且线程将再次调用 wait()


正如其他一些答案所提到的,Java 1.5 引入了一个新的并发库(在 java.util.concurrent 包中),该库旨在为等待/通知机制提供更高级别的抽象。使用这些新功能,您可以像这样重写原始示例:

public class BlockingQueue<T> {

    private Queue<T> queue = new LinkedList<T>();
    private int capacity;
    private Lock lock = new ReentrantLock();
    private Condition notFull = lock.newCondition();
    private Condition notEmpty = lock.newCondition();

    public BlockingQueue(int capacity) {
        this.capacity = capacity;
    }

    public void put(T element) throws InterruptedException {
        lock.lock();
        try {
            while(queue.size() == capacity) {
                notFull.await();
            }

            queue.add(element);
            notEmpty.signal();
        } finally {
            lock.unlock();
        }
    }

    public T take() throws InterruptedException {
        lock.lock();
        try {
            while(queue.isEmpty()) {
                notEmpty.await();
            }

            T item = queue.remove();
            notFull.signal();
            return item;
        } finally {
            lock.unlock();
        }
    }
}

当然,如果您确实需要一个阻塞队列,那么您应该使用 BlockingQueue 接口。

另外,对于这样的东西,我强烈推荐 Java Concurrency在实践中,因为它涵盖了您可能想了解的有关并发相关问题和解决方案的所有内容。

The wait() and notify() methods are designed to provide a mechanism to allow a thread to block until a specific condition is met. For this I assume you're wanting to write a blocking queue implementation, where you have some fixed size backing-store of elements.

The first thing you have to do is to identify the conditions that you want the methods to wait for. In this case, you will want the put() method to block until there is free space in the store, and you will want the take() method to block until there is some element to return.

public class BlockingQueue<T> {

    private Queue<T> queue = new LinkedList<T>();
    private int capacity;

    public BlockingQueue(int capacity) {
        this.capacity = capacity;
    }

    public synchronized void put(T element) throws InterruptedException {
        while(queue.size() == capacity) {
            wait();
        }

        queue.add(element);
        notify(); // notifyAll() for multiple producer/consumer threads
    }

    public synchronized T take() throws InterruptedException {
        while(queue.isEmpty()) {
            wait();
        }

        T item = queue.remove();
        notify(); // notifyAll() for multiple producer/consumer threads
        return item;
    }
}

There are a few things to note about the way in which you must use the wait and notify mechanisms.

Firstly, you need to ensure that any calls to wait() or notify() are within a synchronized region of code (with the wait() and notify() calls being synchronized on the same object). The reason for this (other than the standard thread safety concerns) is due to something known as a missed signal.

An example of this, is that a thread may call put() when the queue happens to be full, it then checks the condition, sees that the queue is full, however before it can block another thread is scheduled. This second thread then take()'s an element from the queue, and notifies the waiting threads that the queue is no longer full. Because the first thread has already checked the condition however, it will simply call wait() after being re-scheduled, even though it could make progress.

By synchronizing on a shared object, you can ensure that this problem does not occur, as the second thread's take() call will not be able to make progress until the first thread has actually blocked.

Secondly, you need to put the condition you are checking in a while loop, rather than an if statement, due to a problem known as spurious wake-ups. This is where a waiting thread can sometimes be re-activated without notify() being called. Putting this check in a while loop will ensure that if a spurious wake-up occurs, the condition will be re-checked, and the thread will call wait() again.


As some of the other answers have mentioned, Java 1.5 introduced a new concurrency library (in the java.util.concurrent package) which was designed to provide a higher level abstraction over the wait/notify mechanism. Using these new features, you could rewrite the original example like so:

public class BlockingQueue<T> {

    private Queue<T> queue = new LinkedList<T>();
    private int capacity;
    private Lock lock = new ReentrantLock();
    private Condition notFull = lock.newCondition();
    private Condition notEmpty = lock.newCondition();

    public BlockingQueue(int capacity) {
        this.capacity = capacity;
    }

    public void put(T element) throws InterruptedException {
        lock.lock();
        try {
            while(queue.size() == capacity) {
                notFull.await();
            }

            queue.add(element);
            notEmpty.signal();
        } finally {
            lock.unlock();
        }
    }

    public T take() throws InterruptedException {
        lock.lock();
        try {
            while(queue.isEmpty()) {
                notEmpty.await();
            }

            T item = queue.remove();
            notFull.signal();
            return item;
        } finally {
            lock.unlock();
        }
    }
}

Of course if you actually need a blocking queue, then you should use an implementation of the BlockingQueue interface.

Also, for stuff like this I'd highly recommend Java Concurrency in Practice, as it covers everything you could want to know about concurrency related problems and solutions.

羞稚 2024-09-02 12:46:05

不是队列示例,但非常简单:)

class MyHouse {
    private boolean pizzaArrived = false;

    public void eatPizza(){
        synchronized(this){
            while(!pizzaArrived){
                wait();
            }
        }
        System.out.println("yumyum..");
    }

    public void pizzaGuy(){
        synchronized(this){
             this.pizzaArrived = true;
             notifyAll();
        }
    }
}

一些要点:
1) 永远不要

 if(!pizzaArrived){
     wait();
 }

总是使用 while(condition),因为

  • a) 线程可以偶尔唤醒
    从等待状态而不是
    由任何人通知。 (即使当
    披萨师傅没有按铃,
    有人会决定尝试吃
    比萨。)。
  • b) 您应该检查
    获得后再次条件
    同步锁。就说披萨吧
    不要永远持续下去。你醒了,
    排队买披萨,但事实并非如此
    对每个人来说都足够了。如果你不这样做
    检查一下,你可能会吃纸! :)
    (可能更好的例子是
    while(!pizzaExists){ 等待(); }。

2)在调用wait/nofity之前必须持有锁(同步)。线程还必须在唤醒之前获取锁。

3)尽量避免在同步块中获取任何锁,并努力不调用外来方法(您不确定它们在做什么的方法)。如果必须的话,请务必采取措施避免僵局。

4) 小心使用notify()。坚持使用notifyAll(),直到你知道自己在做什么。

5)最后但并非最不重要的一点是,阅读Java 并发实践

Not a queue example, but extremely simple :)

class MyHouse {
    private boolean pizzaArrived = false;

    public void eatPizza(){
        synchronized(this){
            while(!pizzaArrived){
                wait();
            }
        }
        System.out.println("yumyum..");
    }

    public void pizzaGuy(){
        synchronized(this){
             this.pizzaArrived = true;
             notifyAll();
        }
    }
}

Some important points:
1) NEVER do

 if(!pizzaArrived){
     wait();
 }

Always use while(condition), because

  • a) threads can sporadically awake
    from waiting state without being
    notified by anyone. (even when the
    pizza guy didn't ring the chime,
    somebody would decide try eating the
    pizza.).
  • b) You should check for the
    condition again after acquiring the
    synchronized lock. Let's say pizza
    don't last forever. You awake,
    line-up for the pizza, but it's not
    enough for everybody. If you don't
    check, you might eat paper! :)
    (probably better example would be
    while(!pizzaExists){ wait(); }.

2) You must hold the lock (synchronized) before invoking wait/nofity. Threads also have to acquire lock before waking.

3) Try to avoid acquiring any lock within your synchronized block and strive to not invoke alien methods (methods you don't know for sure what they are doing). If you have to, make sure to take measures to avoid deadlocks.

4) Be careful with notify(). Stick with notifyAll() until you know what you are doing.

5)Last, but not least, read Java Concurrency in Practice!

愿与i 2024-09-02 12:46:05

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

Josh Bloch,Effective Java 2nd Edition,第 69 条:优先使用并发实用程序而不是 waitnotify(强调他的):

鉴于正确使用 waitnotify 的困难,您应该使用更高级别的并发实用程序 [...]与 java.util.concurrent很少有理由在新代码中使用waitnotify

Even though you asked for wait() and notify() specifically, I feel that this quote is still important enough:

Josh Bloch, Effective Java 2nd Edition, Item 69: Prefer concurrency utilities to wait and notify (emphasis his):

Given the difficulty of using wait and notify correctly, you should use the higher-level concurrency utilities instead [...] using wait and notify directly is like programming in "concurrency assembly language", as compared to the higher-level language provided by java.util.concurrent. There is seldom, if ever, reason to use wait and notify in new code.

眉目亦如画i 2024-09-02 12:46:05

您看过这个Java 教程吗?

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

至少我就是这么做的。我不是并发专家,因此我尽可能避免手动处理线程。

Have you taken a look at this Java Tutorial?

Further, I'd advise you to stay the heck away from playing with this kind of stuff in real software. It's good to play with it so you know what it is, but concurrency has pitfalls all over the place. It's better to use higher level abstractions and synchronized collections or JMS queues if you are building software for other people.

That is at least what I do. I'm not a concurrency expert so I stay away from handling threads by hand wherever possible.

红ご颜醉 2024-09-02 12:46:05

例子

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
     }

}

Example

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
     }

}
戒ㄋ 2024-09-02 12:46:05

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

我们系统中的三个组件:

  1. 队列 [缓冲区] - 在线程之间共享的固定大小队列
  2. 生产者 - 线程在缓冲区中生成/插入值
  3. 消费者 - 线程从缓冲区消耗/删除值

生产者线程:
生产者将值插入缓冲区,直到缓冲区已满。
如果缓冲区已满,生产者调用 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();
        }
    }
}

UTIL 方法:

    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

The question asks for a wait() + notify() involving a queue(buffer). The first thing that comes to mind is a producer-consumer scenario using a buffer.

Three Components in our system:

  1. Queue [Buffer] - A fixed-size queue shared between threads
  2. Producer - A thread produces/inserts values to the buffer
  3. Consumer - A thread consumes/removes values from the buffer

PRODUCER THREAD:
The producer inserts values in the buffer and until the buffer is full.
If the buffer is full, the producer call wait() and enters the wait stage, until the consumer awakes it.

    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();
        }
    }
}

CONSUMER THREAD:
Consumer thread removes value from the buffer until the buffer is empty.
If the buffer is empty, consumer calls wait() method and enter wait state until a producer sends a notify signal.

    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();
        }
    }
}

UTIL METHOD:

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

Application Code:

    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();
}

A Sample Output:

 ^^^ 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
澉约 2024-09-02 12:46:05

对于等待通知的简单场景,我们将考虑 2 个线程:

1)线程“计算”,它为我们提供从 0 到 5 的所有数字的总和

2)线程“ >WaitNotifyDemo”,这是主线程

目标:我们希望WaitNotifyDemo线程等待,直到Calculate线程完成计算

步骤1]首先让我们创建一个线程来计算sum:

class Calculate extends Thread {
int sum;

@Override
public void run() {
    synchronized (this) {
        for (int i = 0; i < 5; i++) {
            sum += i;
            System.out.println("Current value of sum : " + sum);
        }
        notify();
    }
}

}

这个类有:

  • 扩展的线程类
  • 我们正在同步(这个),因为主线程必须锁定“计算”线程
  • 计算数字总和直到 5

第 2 步] 让我们创建使用 wait 方法的类它用于使主线程直到计算完成

public class WaitNotifyDemo {

public static void main(String[] args) {
    Calculate t = new Calculate();
    t.start();
    synchronized (t) {
        try {
            t.wait();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("final total : " + t.sum);
    }
}

这个类有:

  • 计算线程的实例
  • 然后我们在该实例上调用 wait() 方法

Output

在此处输入图像描述

所以我们可以看到我们在一个对象上调用了 wait ,这使得主线程等待计算,然后执行该类的剩余代码。

For a simple scenario of wait notify we will consider 2 threads :

1)Thread "Calculate" which gives us sum of all number from 0 to 5

2)Thread "WaitNotifyDemo" which is main thread

Objective : We want WaitNotifyDemo thread to wait till Calculate thread completes the calculation

Step 1] First lets create a thread that calculates the sum:

class Calculate extends Thread {
int sum;

@Override
public void run() {
    synchronized (this) {
        for (int i = 0; i < 5; i++) {
            sum += i;
            System.out.println("Current value of sum : " + sum);
        }
        notify();
    }
}

}

This class has :

  • Thread Class extended
  • We are synchronizing(this) as Main thread must have lock on "Calculate" thread
  • Calculating sum of numbers till 5

Step 2] lets create class which uses wait method which is used to make the Main thread till calculation completes

public class WaitNotifyDemo {

public static void main(String[] args) {
    Calculate t = new Calculate();
    t.start();
    synchronized (t) {
        try {
            t.wait();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("final total : " + t.sum);
    }
}

This class has :

  • Instance of Calculate Thread
  • Then we call wait() method on that instance

Output

enter image description here

So we can see that we have called wait on an object which makes main thread wait for calculation and then executes remaining code of the class.

断念 2024-09-02 12:46:05

线程中 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());
   }
}

Example for wait() and notifyall() in Threading.

A synchronized static array list is used as resource and wait() method is called if the array list is empty. notify() method is invoked once a element is added for the array list.

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());
   }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文