【发布时间】:2019-11-08 22:23:10
【问题描述】:
我是多线程新手,非常感谢一些帮助。
编辑的代码和问题
我想使用 ReentrantLock 类来控制对两个 ArrayList 的访问。第一个是orderList,而第二个是preparedOrders ArrayList。类 Chef(扩展 Thread)的两个对象每次都希望从数组列表中删除一个订单,随机休眠一段时间,然后将订单放入preparedOrders 数组列表中,直到 OrdersList 为空。这是我当前的代码:
厨师班
import java.util.concurrent.locks.ReentrantLock;
public class Chef extends Thread{
private String name;
private ReentrantLock orderLock;
private ReentrantLock preparedLock;
private String orderName;
private Object useForLocking = new Object();
public Chef(String name, ReentrantLock orderLock, ReentrantLock preparedLock){
this.name = name;
this.orderLock = orderLock;
this.preparedLock = preparedLock;
}
public void run(){
while(Restaurant.orderList.size()>0){
try{
getOrder();
System.out.println(name +" is preparing "+orderName+"\n");
Thread.sleep(Math.round(Math.random()*100));
outputOrder();
}catch(Exception e){
System.out.println("run exception: "+e+"\n");
}
}
}
public void getOrder(){
if(orderLock.tryLock()){
orderLock.lock();
try{
orderName = Restaurant.orderList.remove(0);
}catch(Exception e){
System.out.println("getOrder exception: "+e+"\n");
}finally{
orderLock.unlock();
synchronized (useForLocking){
useForLocking.notify();
}
}
}else{
try{
synchronized (useForLocking){
useForLocking.wait();
}
}catch(Exception e){
System.out.println("getOrder wait exception: "+e+"\n");
}
}
}
public void outputOrder(){
if(preparedLock.tryLock()){
preparedLock.lock();
try{
Restaurant.preparedOrders.add(orderName);
}catch(Exception e){
System.out.println("outputOrder exception: "+e+"\n");
}finally{
preparedLock.unlock();
synchronized (useForLocking){
useForLocking.notify();
}
}
}else{
try{
synchronized (useForLocking){
useForLocking.wait();
}
}catch(Exception e){
System.out.println("outputOrder wait exception: "+e+"\n");
}
}
}
}
餐厅类(主)
import java.util.concurrent.locks.ReentrantLock;
import java.util.ArrayList;
public class Restaurant{
public static ArrayList<String> orderList = new ArrayList<String>();
public static ArrayList<String> preparedOrders = new ArrayList<String>();
public static void main(String[] args) {
orderList.add("Cheese Pizza");
orderList.add("Hotdog");
orderList.add("Hamburger");
orderList.add("Cheese burger");
orderList.add("Chicken Nuggets");
orderList.add("Chicken Burger");
ReentrantLock orderLock = new ReentrantLock();
ReentrantLock preparedLock = new ReentrantLock();
Chef c1 = new Chef("Chef John", orderLock, preparedLock);
Chef c2 = new Chef("Chef Mark", orderLock, preparedLock);
c1.start();
c2.start();
}
}
输出
Chef John is preparing Cheese Pizza
Chef John is preparing Hotdog
Chef John is preparing Hamburger
Chef John is preparing Cheese burger
Chef John is preparing Chicken Nuggets
Chef John is preparing Chicken Burger
为什么第一个线程没有解锁?
【问题讨论】:
-
这不是一个非常简洁的问题。 stackoverflow.com/help/minimal-reproducible-example /
IllegalMonitorStateException被抛出,因为在对象上调用notifyAll或wait的前提是该特定对象被synchronized锁定。对于java.util.concurrent.locks,您需要使用其他方法。 -
@TomHawtin-tackline 你能提供一些示例代码吗?
-
@TomHawtin-tackline 我已经编辑了我的代码(这次只关注厨师),但它仍然没有提供想要的功能。有什么帮助吗?
-
ConditionAPI 文档中有一个使用带有Locks 的监控方法的示例。 docs.oracle.com/en/java/javase/13/docs/api/java.base/java/util/… 你需要用Lock.newCondition创建一个Condition并确保你调用await(如wait)和signalAll(如notifyAll)在Condition的同一个实例上. -
@NathanHughes 显然。如果这是一个简单的错误,我可以自己修复它。
标签: java multithreading arraylist locking