【问题标题】:Thread isn't resuming execution after notify()notify() 后线程没有恢复执行
【发布时间】:2018-11-13 00:45:39
【问题描述】:

我有两个班级(Customer 和 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!
线程 7 已被唤醒

请帮忙。谢谢你。 :)

【问题讨论】:

  • 请格式化您的代码。请包含 full minimal reproducible example - 您可能只是没有从队列中获取正在等待的线程,但您还没有包含设置线程的代码。而且,正如 Thread 的 Javadoc 中所提到的 - 您不应该在 Thread 对象上调用 wait/notify,因为 Thread 对象已经将这些用于自己的目的。 (“建议应用程序不要在 Thread 实例上使用 wait、notify 或 notifyAll。”)
  • 不推荐使用 Thread 对象的 waitnotify 方法,因为这会干扰它们的操作。考虑让 Customer 实现 Runnable 而不扩展任何东西,然后使用 new Thread(customer) 创建线程。
  • 嗨@ErwinBolwidt,我已经添加了可以重现我的问题的最小和完整代码:)
  • 嗨@VGR ..我修改了代码并尝试使用锁定对象,但我仍然面临同样的问题:(

标签: java multithreading parallel-processing wait notify


【解决方案1】:

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

代码中可能存在其他问题。如需更多帮助,请发布 Mcve。
其他一些 cmets:

CustomerGenerator 中,您通过以下方式将所有收银台的引用传递给Customerfinal 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);
}

【讨论】:

    【解决方案2】:

    只需从 Till 等待,直到 Queue 获得超过零个元素。将自己加入队列后,从客户线程通知 Till。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-29
      • 2011-03-20
      • 1970-01-01
      • 2013-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多