我的多线程有问题,链接列表 poll(),而offer()返回null,因为它已经确保它不是空的 wait()并通知(),为了更清楚,我遇到与this guy类似的问题。
解决方案:
根据this guy,他通过以下方式解决问题:
这里的问题是我使用2个线程来处理队列,不应该使用 正常队列。如有任何问题我会反馈
意味着他在同一个对象上使用2个线程,这意味着两个线程都希望执行这些作业会导致两者都无法执行,因为它返回null 。要解决它,你只需要运行一个线程或同步?如上所述:
只要您对其进行同步或拍摄,就可以使用“普通队列” 确保线程安全的其他措施
我的问题
我仍然希望有多个线程处理同一个对象,但是同步和锁定。完成后,它仍然显示与锁定后之前相同的问题。
有问题的代码
导致问题的代码,也许我的锁实现是错误的,所以它不会工作?我会一步一步解释:
public void CleanBus(String CleanerName) {
Bus bus;
Boolean BusClean = false;
synchronized (ListBusEngineFix) {
while (ListBusEngineFix.size() == 0) {
try {
ListBusEngineFix.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
上面的代码用于确保List MUST NOT EMPTY ,如果它传递了此代码意味着ListBusEngineFix
不为空,并且可以在此之后进行轮询。
确保列表不为空后,我会尝试轮询,并将其存储在另一个列表中
bus = (Bus) ((LinkedList<?>) ListBusEngineFix).poll();
try {
Thread.sleep(200);
System.out.println("Cleaners: " + CleanerName + "cleaning " + bus.getBusName());
BusClean = new Random().nextBoolean();
} catch (InterruptedException e) {
e.printStackTrace();
}
((LinkedList<Bus>) ListBusClean).offer(bus);
}
如此处所示,我仍在同步方法中,我尝试轮询并且延迟200ms ,然后开始打印轮询值的值。
结果
Exception in thread "Thread-4" java.lang.NullPointerException
at BusShop.CleanBus(BusShop.java:130)
at Cleaner.CleanBus(Cleaner.java:25)
at Cleaner.run(Cleaner.java:13)
at java.lang.Thread.run(Thread.java:748)
Exception in thread "Thread-3" java.lang.NullPointerException
at BusShop.CleanBus(BusShop.java:130)
at Cleaner.CleanBus(Cleaner.java:25)
at Cleaner.run(Cleaner.java:13)
at java.lang.Thread.run(Thread.java:748)
正如看到的结果,我们已经知道两个线程在仍处于同步锁定时想要访问
附加代码
这是使线程能够更早地运行CleanBus函数的代码。
@Override
public void run() {
CleanBus();
}
private void CleanBus() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
while (true) {
synchronized(this) {
busShop.CleanBus(CleanerName);
notify();
}
}
}
对于Main我创建2个线程,如下所示,没有问题。
Cleaner cleaner = new Cleaner(busShop, "Cleaner 1");
Cleaner cleaner2 = new Cleaner(busShop, "Cleaner 2");
Thread thCleaner = new Thread(cleaner);
Thread thCleaner2 = new Thread(cleaner2);
thCleaner.start();
thCleaner2.start();
notify()来自哪里唤醒 wait()?
//Unshown code are poll offer, so that ListBusEngineFix notify, basically it will not empty.
if (ListBusEngineFix.size() != 0) {
synchronized (ListBusEngineFix) {
ListBusEngineFix.notify();
}
}
HINT
这并不是每次都显示,大约10次尝试,有2次空例外,有时甚至更糟。原因可能是其他线程忙,所以只有一个访问它,并且没有问题。
好的,我的同步无法为一个线程锁定一个对象是否存在问题?