简体   繁体   English

Java 线程在 join() 中被阻塞

[英]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.我有以下简单的代码,我在其中放入和取出表示为 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.我不明白为什么我的线程在join()方法中被阻塞。 From main I call as follow:从主要我调用如下:

eService = new EmailService();
Email e1 = new Email(client1, client2, "content1");
eService.sendNotificationEmail(e1);
eService.close();

Without running it...不运行它...

  • The close() method holds lock at the time it calls thread.join() and waits on thread (forever) close()方法在调用thread.join()时持有lock并等待thread (永远)
  • thread is waiting to reacquire lock so cannot run thread正在等待重新获取lock因此无法运行

Both are now waiting on each other, this is a deadlock .双方现在都在互相等待,这是一个僵局 Try moving the Thread.join() after the synchronized block:尝试在synchronized块之后移动Thread.join()

    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. @drekbour 解释了您的程序如何挂在join()调用中,但仅供参考:这是您的程序挂起的一种方式。 This is called lost notification.这称为丢失通知。

Your main thread creates a new EmailService instance.您的主线程创建一个新的EmailService实例。 The new instance creates its thread and calls thread.start() *BUT* it could take some time for the thread to actually start running.新实例创建它的线程并调用thread.start() *但 * 线程实际开始运行可能需要一些时间。 Meanwhile...同时...

Your main thread creates a new Email instance, and calls eService.sendNotificationEmail(...) .您的主线程创建一个新的Email实例,并调用eService.sendNotificationEmail(...) That function adds the new message to the queue, locks the lock , notifies the lock, and then waits on the lock.该函数将新消息添加到队列中,锁定lock ,通知锁,然后等待锁。

Finally, The service thread starts up, enters its run() method, locks the lock, and then it calls lock.wait() .最后,服务线程启动,进入其run()方法,锁定锁,然后调用lock.wait()

At this point, the program will be stuck because each thread is waiting to be notified by the other.此时程序会卡住,因为每个线程都在等待对方的通知。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM