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();
Advertisement
Answer
Without running it…
- The
close()
method holdslock
at the time it callsthread.join()
and waits onthread
(forever) thread
is waiting to reacquirelock
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"); }