通知()后线程未恢复执行

Thread isn't resuming execution after notify()

我有两个 类(Customer 和 Till)。客户线程一直等到收银员线程通知它。在我的程序中,客户线程在收到 till 线程通知后不执行它的代码。 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
Thread-7 已收到通知!

预期输出:

线程 7 等待
线程 1 唤醒:线程 7
Thread-7 已收到通知!
Thread-7 已被唤醒

请帮忙。谢谢你。 :)

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

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 应该演示 问题 ,并且 不是 您的应用程序。

代码中可能还有其他问题。如需更多帮助,请 post Mcve.
其他一些评论:

CustomerGenerator 中,您通过以下方式将所有收银台的引用传递给 Customerfinal Customer customer = new Customer(till_set); 稍后用于选择收银台。我认为直到选择计算最好在另一个 class 中完成,比如 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);
}