一个线程不会 运行 直到另一个线程结束
One thread does not run till the other one is ended
我正在做一个简单的生产者消费者问题。服务员是生产者,厨师是消费者。我已经实现它,以便 Chef 线程等待,直到 Waiter 通知它队列中有传入订单。
public class Main {
public static void main(String args[]) {
final Queue<Integer> sharedQ = new LinkedList<Integer>();
Thread waiter = new Waiter(sharedQ);
Thread chef = new Chef(sharedQ);
waiter.start();
chef.start();
}
}
class Items{
String[] items = {" ", "Sandwich", "Cereal", "Coffee", "Pizza"};
int[] time = {0,5,3,3,7};
String getItem(int value){
return items[value];
}
int getTime(int value){
return time[value];
}
}
class Waiter extends Thread{
private final Queue<Integer> sharedQ;
static int ord = 0;
Items item = new Items();
SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm:ss aa");
public Waiter(Queue<Integer> sharedQ) {
super("Waiter");
this.sharedQ = sharedQ;
}
@Override
public void run() {
int choice = 1;
Scanner in = new Scanner(System.in);
while(choice >= 1 && choice <= 4) {
synchronized (sharedQ) {
System.out.print("Enter item id :");
choice = in.nextInt();
if(choice >= 1 && choice <= 4){
ord++;
System.out.println("Order Number: ORD"+ord+" for " + item.getItem(choice)+" has been placed at +"+dateFormat.format(new Date()).toString());
sharedQ.add(choice);
sharedQ.notifyAll();
}
}
}
}
}
class Chef extends Thread{
private final Queue<Integer> sharedQ;
Items item = new Items();
static int ord = 0;
SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm:ss aa");
public Chef(Queue<Integer> sharedQ) {
super("Chef");
this.sharedQ = sharedQ;
}
@Override
public void run() {
int choice;
while(true) {
try{
synchronized (sharedQ) {
//waiting condition - wait until Queue is not empty
while (sharedQ.size() == 0) {
sharedQ.wait();
}
System.out.println(sharedQ.size());
choice = sharedQ.poll();
System.out.println("abc");
ord++;
System.out.println("Chef : Picked up ORD"+ord+" at "+ dateFormat.format(new Date()).toString());
System.out.println("Chef: Cooking "+item.getItem(choice));
Thread.sleep(60*1000*item.getTime(choice));
System.out.println("Chef : Finished making "+item.getItem(choice)+" at "+ dateFormat.format(new Date()).toString());
sharedQ.notify();
}
}
catch (InterruptedException ex) {
System.out.println("Exception in chef function");
}
}
}
}
但是,Chef 线程直到 Waiter 线程结束才响应。
有线索吗?
尝试移动
System.out.print("Enter item id :");
choice = in.nextInt();
超出 synchronized
部分。
出现问题是因为 Waiter 线程将大部分时间花在 in.nextInt()
方法中等待用户输入。一直获取锁。当用户输入数字并释放锁时,它几乎会立即返回以进行下一次迭代。如果多个线程尝试获取锁,则决定下一个线程将获得锁的调度程序并不完美,因此它会唤醒 Chef 线程但不会立即获取锁。我们有两个线程都试图获得锁的情况。如果您输入多个数字,您会看到 Chef 有时会被锁定,但并非总是如此。
问题是 Waiter
永远不会释放共享队列上的锁,因此 Chef
永远无法从中读取。
更好的方法是使用 BlockingQueue
implementation, like LinkedBlockingQueue
, 删除程序中 synchronized
块的使用。
对于新应用程序,应避免使用内部锁(synchronized
块)、Thread
实例和 wait()
/notify()
调用,最好使用 ExecutorService
和 java.util.concurrent
包中的实用程序。
我正在做一个简单的生产者消费者问题。服务员是生产者,厨师是消费者。我已经实现它,以便 Chef 线程等待,直到 Waiter 通知它队列中有传入订单。
public class Main {
public static void main(String args[]) {
final Queue<Integer> sharedQ = new LinkedList<Integer>();
Thread waiter = new Waiter(sharedQ);
Thread chef = new Chef(sharedQ);
waiter.start();
chef.start();
}
}
class Items{
String[] items = {" ", "Sandwich", "Cereal", "Coffee", "Pizza"};
int[] time = {0,5,3,3,7};
String getItem(int value){
return items[value];
}
int getTime(int value){
return time[value];
}
}
class Waiter extends Thread{
private final Queue<Integer> sharedQ;
static int ord = 0;
Items item = new Items();
SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm:ss aa");
public Waiter(Queue<Integer> sharedQ) {
super("Waiter");
this.sharedQ = sharedQ;
}
@Override
public void run() {
int choice = 1;
Scanner in = new Scanner(System.in);
while(choice >= 1 && choice <= 4) {
synchronized (sharedQ) {
System.out.print("Enter item id :");
choice = in.nextInt();
if(choice >= 1 && choice <= 4){
ord++;
System.out.println("Order Number: ORD"+ord+" for " + item.getItem(choice)+" has been placed at +"+dateFormat.format(new Date()).toString());
sharedQ.add(choice);
sharedQ.notifyAll();
}
}
}
}
}
class Chef extends Thread{
private final Queue<Integer> sharedQ;
Items item = new Items();
static int ord = 0;
SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm:ss aa");
public Chef(Queue<Integer> sharedQ) {
super("Chef");
this.sharedQ = sharedQ;
}
@Override
public void run() {
int choice;
while(true) {
try{
synchronized (sharedQ) {
//waiting condition - wait until Queue is not empty
while (sharedQ.size() == 0) {
sharedQ.wait();
}
System.out.println(sharedQ.size());
choice = sharedQ.poll();
System.out.println("abc");
ord++;
System.out.println("Chef : Picked up ORD"+ord+" at "+ dateFormat.format(new Date()).toString());
System.out.println("Chef: Cooking "+item.getItem(choice));
Thread.sleep(60*1000*item.getTime(choice));
System.out.println("Chef : Finished making "+item.getItem(choice)+" at "+ dateFormat.format(new Date()).toString());
sharedQ.notify();
}
}
catch (InterruptedException ex) {
System.out.println("Exception in chef function");
}
}
}
}
但是,Chef 线程直到 Waiter 线程结束才响应。 有线索吗?
尝试移动
System.out.print("Enter item id :");
choice = in.nextInt();
超出 synchronized
部分。
出现问题是因为 Waiter 线程将大部分时间花在 in.nextInt()
方法中等待用户输入。一直获取锁。当用户输入数字并释放锁时,它几乎会立即返回以进行下一次迭代。如果多个线程尝试获取锁,则决定下一个线程将获得锁的调度程序并不完美,因此它会唤醒 Chef 线程但不会立即获取锁。我们有两个线程都试图获得锁的情况。如果您输入多个数字,您会看到 Chef 有时会被锁定,但并非总是如此。
问题是 Waiter
永远不会释放共享队列上的锁,因此 Chef
永远无法从中读取。
更好的方法是使用 BlockingQueue
implementation, like LinkedBlockingQueue
, 删除程序中 synchronized
块的使用。
对于新应用程序,应避免使用内部锁(synchronized
块)、Thread
实例和 wait()
/notify()
调用,最好使用 ExecutorService
和 java.util.concurrent
包中的实用程序。