java - Sun 的 Thread.join 方法是否因为使用 Thread 对象同步而损坏?

标签 java multithreading join timeout

通过运行测试程序和查看源代码,可以清楚地看出 Sun 实现的方法并没有简单地让出时间给指定的线程,而是实际上它首先尝试获取线程对象上的监视器。具体来说,该方法实现为“同步”。

请注意,wait 和 notify 方法也需要监视器,但与 join 不同的是,调用者有责任在调用之前获取监视器,文档中明确说明了这一点。 Javadocs 中没有记录加入取决于监视器的事实,尽管做出推断可能是很自然的。

文档是否足够清晰?

此外,如果线程由于某种原因无法获得监视器,它会挂起,也许永远挂起。在等待监视器时,线程不可中断,也不会像文档中描述的那样抛出 InterruptedException。另一方面,除非出现编程错误,否则线程无法获得监视器的原因尚不清楚。

担心争夺监视器是否合理?

最后,让超时的操作依赖于获取监视器似乎是不合适的,除非可以保证获取监视器的任务本身会超时。

依赖于 join() 的监视器是否是一个合理的实现?甚至可以通过任何其他方式实现它吗?

最佳答案

Thread.join 调用 wait,释放监视器。因为这意味着“加入”线程也不会阻止任何其他线程调用 join,所以我怀疑这会回答您的大多数其他查询。它不会阻止另一个调用者在线程的监视器上进行同步(哦,公共(public)监视器的乐趣),但这意味着常见情况工作正常。

为了证明您的第一点是错误的,这里有一个创建 10 个线程的示例,每个线程在主线程上等待 5 秒。 (请忽略 Date 可怕的异常吞噬和滥用。它仅用于研究线程行为。)

import java.util.*;

public class Test
{
    public static void main(String[] args) throws Exception
    {
        for (int i=0; i < 10; i++)
        {
            new Thread(new ThreadJoiner(Thread.currentThread(), i))
                     .start();
        }
        try
        {
            Thread.sleep(10000);
        }
        catch (InterruptedException e) {}
    }

    private static class ThreadJoiner implements Runnable
    {
        private final Thread threadToJoin;
        int id;

        public ThreadJoiner(Thread threadToJoin, int id)
        {
            this.threadToJoin = threadToJoin;
            this.id = id;
        }

        public void run()
        {
            try
            {
                System.out.println("Thread " + id +
                                   " waiting at " + new Date());
                threadToJoin.join(5000);
                System.out.println("Thread " + id +
                                   " finished waiting at " + new Date());
            }
            catch (InterruptedException e) {}
        }
    }
}

如果您运行它,您会看到所有线程几乎同时开始和结束它们的等待。如果您的担忧是有根据的,您不会像您那样“错开”结束。

关于java - Sun 的 Thread.join 方法是否因为使用 Thread 对象同步而损坏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/813157/

相关文章:

java - Java中链表的链表

android - Recycler View 在它的主框架上做太多的工作

java - 数据库多重内连接

MySql 连接 3 个表 - 多重连接

sql - 如果一个或多个表中可能缺少该键,您能否在同一个键上连接三个表?

java - 如何从 Spring Boot Restful GET 调用返回对象属性的子集?

java - 如何获取kafka的消费者offset值

java - JScrollPane 阻止与内容交互

windows - 在 Windows 中枚举线程

python - 在 WSGI 环境中启动一个单独的线程