在notify()

时间:2018-11-13 00:45:40

标签: java multithreading parallel-processing wait notify

我有两个班级(Customer和Till)。客户线程等待,直到一个直到线程通知它。在我的程序中,客户线程在直到直到线程被通知之后才执行代码。直到线程继续执行。

Customer.java (客户线程扩展了线程)

import java.util.concurrent.*;
import java.util.*;

public class Customer extends Thread
{
    Random random_generator = new Random();

    public int minimumQueueLength;
    public Set set;
    public Iterator iterator;
    public boolean placed_in_queue;

    public List<Integer> queue_length_list;
    public CopyOnWriteArrayList till_set = new CopyOnWriteArrayList();
    public Till till, till_to_join;
    public final Object lock;

    public Customer(CopyOnWriteArrayList till_set)
    {
        this.till_set = till_set;
        this.placed_in_queue = false;
        queue_length_list = new ArrayList<Integer>();
        lock = new Object();
    }

    public void run()
    {   
        try 
        {
            place_in_queue();
        } 
        catch (InterruptedException e1)
        {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        if(placed_in_queue)
        {   
            synchronized(this.lock)
            {

                System.out.println(this.getName()+" waiting");

                try {
                    this.lock.wait();

                    System.out.println(this.getName()+" has been woken");

                } catch (InterruptedException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            }
        }
        else
        {
        }
    }

    public void place_in_queue() throws InterruptedException
    {
        placed_in_queue = false;
        iterator = till_set.iterator();

        while(iterator.hasNext())
        {
            till = (Till)iterator.next();
            queue_length_list.add(till.customer_queue.size());
        } 

        minimumQueueLength = 
                queue_length_list.indexOf(Collections.min(queue_length_list));

        if(minimumQueueLength < 5)
        {
            try 
            {
                till_to_join = (Till)till_set.get(minimumQueueLength);
                till_to_join.customer_queue.put(this);
                placed_in_queue = true;
            } 
            catch (InterruptedException e) 
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

Till.java (直到线程扩展了线程)

import java.util.HashMap;
import java.util.Iterator;
import java.util.Random;
import java.util.concurrent.*;

public class Till extends Thread
{
    BlockingQueue<String> item_queue = new ArrayBlockingQueue<String>(200);
    BlockingQueue<Customer> customer_queue = new ArrayBlockingQueue<Customer>(10);

    public Random random;
    public Customer c;

    public Till(BlockingQueue<String> item_queue) throws InterruptedException
    {
        this.item_queue = item_queue;
        random = new Random();
    }

    public void run()
    {                   
        while(true)
        {   
            try 
            {
                c = customer_queue.take();

                synchronized(c.lock)
                {
                    System.out.println(this.getName()+" Waking up : "+c.getName());
                    c.lock.notify();
                    System.out.println(c.getName()+" has been notified!");
                }           
            } 
            catch (InterruptedException e) 
            {
                e.printStackTrace();
            }
        }
    }
}

CustomerGenerator.java

import java.util.*;
import java.util.concurrent.*;

public class CustomerGenerator extends Thread
{
    public int customer_generation_rate;

    //0 - slow
    //1 - fast

    public Random random_generator;

    public static BlockingQueue<String> item_queue = new ArrayBlockingQueue<String>(200);
    public static CopyOnWriteArrayList till_set = new CopyOnWriteArrayList();

    public int i;

    public CustomerGenerator(int customer_generation_rate, CopyOnWriteArrayList till_set)
    {
        this.customer_generation_rate = customer_generation_rate;
        this.till_set = till_set;
        this.i = 0;
        random_generator = new Random();    
    }

    public void run()
    {
        while(i<1)
        {
            switch(customer_generation_rate)
            {         
            case 0 : try 
            {
                Thread.sleep(random_generator.nextInt(1000));
            } 
            catch (InterruptedException e) 
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            break;

            case 1 : try
            {
                Thread.sleep(random_generator.nextInt(500));
            }
            catch(InterruptedException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            break;

            default : customer_generation_rate = 0;
            break;
            }

            Customer customer = new Customer(till_set);
            customer.start();
            total_customer_count++;
            i++;
        }
    }
} 

Driver.java

import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Driver
{
    public static BlockingQueue<String> item_queue = new ArrayBlockingQueue<>(200);

    public static CopyOnWriteArrayList<Till> till_set = new CopyOnWriteArrayList<Till>();

    public static Set set;
    public static Iterator iterator;

    public static int i;

    public static final int till_count = 5;

    public static Thread till_thread;

    public static Till till_object;

    public static ExecutorService till_service = Executors.newFixedThreadPool(5);

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

        for(i=0; i<till_count; i++)
        {
            till_object = new Till(item_queue);
            till_set.add(till_object);
        }

        final CustomerGenerator customer_generator = new CustomerGenerator(0, till_set);
        customer_generator.start();

        Thread.sleep(5000);

        for(final Till t : till_set)
        {
            till_service.submit(t);
        }
    }
}

获得的输出:

线程7等待中
线程1唤醒:线程7
线程7已被通知!

预期输出:

线程7等待中
线程1唤醒:线程7
线程7已通知!
线程7已被唤醒

请帮助。谢谢。 :)

2 个答案:

答案 0 :(得分:0)

只需从耕作开始,直到队列获得多于零个元素。将自己添加到队列中之后,从客户线程中通知Till。

答案 1 :(得分:0)

CustomerGenerator仅在被调用时生成一个客户。制作它的mcve版本非常清楚:

//i was initialized: i=0;
public void run()
{
    while(i<1)
    {
        final Customer customer = new Customer(till_set);
        customer.start();
        i++;
    }
}

我认为那不是你的意思。
我发现mcve是一种非常有用的技术。它不仅使帮助变得容易得多,而且 是功能强大的调试工具。很多情况下,在准备一个时,您很可能会发现问题。 mcve应该演示问题,而不是您的应用。

代码中可能还有其他问题。如需更多帮助,请发布 M cve。
其他一些评论:

CustomerGenerator中,您通过以下方式将所有耕作的引用传递给Customer:  final Customer customer = new Customer(till_set);,稍后用于选择耕作。我认为直到选择计算最好在另一个类中完成,例如TillsManager,它可以让所有的顾客都在等着耕种。

Driver中定义

 public static Till till_object; 
 for(i=0; i<5 ; i++)
 {
    till_object = new Till(item_queue);
    till_set.add(till_object);
 }

表示您最终将得到till_set中相同对象的5倍。我想你想要的是:

 for(i=0; i<till_count; i++)
 {
    Till till_object = new Till(item_queue);
    till_set.add(till_object);
}