有两种方法可以将消息推送到arraylist,而其他方法则从arraylist中检索消息。两种方法都是同步的。 我创建了两个线程,一个用于将消息推送到arraylist,另一个用于检索。两个线程处于死锁状态。如何解决它
以下是推送和显示消息的代码
public class FetchCurrentTime {
static final int MAXMESSAGE = 5;
private List<String> messages = new ArrayList<String>();
public synchronized void putTime(){
while(messages.size() != MAXMESSAGE){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Calendar cal = Calendar.getInstance();
messages.add(dateFormat.format(cal.getTime()).toString());
}
notify();
}
public synchronized String getTime(){
String message= "Unable to fetch time";
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
if(!message.isEmpty()){
message = messages.remove(messages.size()-1);
}
notify();
return message;
}
}
以下是生产者和消费者代码
public class ProduceTime extends Thread {
FetchCurrentTime fc ;
public ProduceTime(FetchCurrentTime fc) {
this.fc = fc;
}
@Override
public void run() {
fc.putTime();
}
}
public class ConsumeTime extends Thread {
FetchCurrentTime fc ;
public ConsumeTime(FetchCurrentTime fc) {
this.fc = fc;
}
@Override
public void run() {
while (true) {
String time = fc.getTime();
System.out.println(time);
}
}
}
这是要测试的代码。
public class GetDate {
public static void main(String[] args) throws InterruptedException {
FetchCurrentTime fc = new FetchCurrentTime();
ProduceTime p = new ProduceTime(fc);
ConsumeTime c = new ConsumeTime(fc);
Thread t1 = new Thread(p);
Thread t2 = new Thread(c);
t1.start();
t2.start();
}
}
答案 0 :(得分:0)
我发现问题出在wait()
和getTime()
中调用putTime()
时,因为两者都在等待另一个通知;从未发生过。
此外,getTime()
中存在拼写错误,应该是messages.isEmpty()
(列表)而不是message.isEmpty()
(字符串)
您可以尝试使用此代码。请注意,它会永远运行,因此您需要处理终止条件。
public synchronized void putTime() {
while (true) { // To ensure list contains 5 elements at any point of time before removal
if (messages.size() >= MAXMESSAGE) {
try {
wait(); // wait issued only when list is full
} catch(InterruptedException e) {
e.printStackTrace();
}
}
while (messages.size() < MAXMESSAGE) {
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Calendar cal = Calendar.getInstance();
messages.add(dateFormat.format(cal.getTime()).toString());
}
notify(); // notify getTime() to resume execution
}
}
public synchronized String getTime() {
String message = "Unable to fetch time";
try {
Thread.sleep(100); // adding delay to help see the output
if (messages.isEmpty()) {
wait(); // wait for putTime() to add messages to the list
}
if (!messages.isEmpty()) {
message = messages.remove(messages.size() - 1);
notify(); // notifies putTime() to add a message to the list; helps keep count to 5
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return message;
}
也就是说,建议使用高级的Thread构造,它有助于实现相同(更容易)和更好的吞吐量。
希望这会有所帮助:)
答案 1 :(得分:0)
请在您的代码中找到以下问题。
注意-使用notifyAll而不是notify。
答案 2 :(得分:-1)
有很多方法可以解决这个问题。每当有两个或多个锁由两个不同的订单中的线程获取时,就会发生死锁。订购是关键部分。
E.g。如果一个线程可以获得put锁定,而另一个线程获取get锁定,反之亦然,那就是死锁。如果每个线程总是首先获取get lock,那么put lock,并在释放get lock之前释放put lock,然后就不可能出现死锁。
要解决这个问题,请使锁明确(例如:synchronized(lockObject){/ *代码* /}),并始终按顺序获取锁,或者只使用一个锁。
另一个解决方案是使用像Akka这样的actor框架。演员抽象锁定,特别适合发送和接收消息。有了演员,就有一个&#34;邮箱&#34;使用同步访问来添加来自其他线程的消息,但是actor本身在其一个线程中串行处理消息。