通知()后线程未恢复执行
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
中,您通过以下方式将所有收银台的引用传递给 Customer
:
final 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);
}
我有两个 类(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
中,您通过以下方式将所有收银台的引用传递给 Customer
:
final 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);
}