I have the following simple code in which I put and take from a Queue represented as an ArrayList.
public class EmailService {
private Queue<Email> emailQueue;
private Object lock;
private volatile boolean run;
private Thread thread;
public void sendNotificationEmail(Email email) throws InterruptedException {
emailQueue.add(email);
synchronized (lock) {
lock.notify();
lock.wait();
}
}
public EmailService() {
lock = new Object();
emailQueue = new Queue<>();
run = true;
thread = new Thread(new Runnable() {
@Override
public void run() {
while (run) {
System.out.println("ruuuning");
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
if (emailQueue.getSize() > 0) {
sendEmail(emailQueue.poll());
}
lock.notify();
}
}
}
private void sendEmail(Email email) {
System.out.println("Sent email from " + email.getFrom() + " to " + email.getTo() + " with content: " + email.getContent());
}
});
thread.start();
}
public void close() throws InterruptedException {
run = false;
synchronized (lock) {
lock.notify();
System.out.println("Thread will join " + thread.isInterrupted());
thread.join();
System.out.println("Thread after join");
}
}
}
I don't understand why my thread is blocked in join()
method. From main I call as follow:
eService = new EmailService();
Email e1 = new Email(client1, client2, "content1");
eService.sendNotificationEmail(e1);
eService.close();
Without running it...
close()
method holds lock
at the time it calls thread.join()
and waits on thread
(forever) thread
is waiting to reacquire lock
so cannot run Both are now waiting on each other, this is a deadlock . Try moving the Thread.join()
after the synchronized
block:
public void close() throws InterruptedException {
run = false;
synchronized (lock) {
lock.notify();
System.out.println("Thread will join " + thread.isInterrupted());
}
thread.join();
System.out.println("Thread after join");
}
@drekbour explained how your program could hang in the join()
call, but FYI: Here's a different way that your program could hang. This is called lost notification.
Your main thread creates a new EmailService
instance. The new instance creates its thread and calls thread.start()
*BUT* it could take some time for the thread to actually start running. Meanwhile...
Your main thread creates a new Email
instance, and calls eService.sendNotificationEmail(...)
. That function adds the new message to the queue, locks the lock
, notifies the lock, and then waits on the lock.
Finally, The service thread starts up, enters its run()
method, locks the lock, and then it calls lock.wait()
.
At this point, the program will be stuck because each thread is waiting to be notified by the other.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.