Skip to content
Advertisement

Java Thread is blocked in join()

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 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");
    }
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement