Java 是太阳';s Thread.join方法已断开,因为它同步了线程对象的usng?

Java 是太阳';s Thread.join方法已断开,因为它同步了线程对象的usng?,java,multithreading,join,timeout,Java,Multithreading,Join,Timeout,通过运行测试程序和查看源代码,很明显,Sun实现的方法并不是简单地给指定的线程分配时间,而是首先尝试获取线程对象上的监视器。具体来说,该方法实现为“同步” 注意,wait和notify方法也需要监视器,但与join不同,调用方有责任在调用之前获取监视器,文档中明确说明了这一点。join依赖于监视器这一事实在Javadocs中没有记录,尽管进行推断可能是很自然的 文档是否足够清晰 此外,如果线程由于某种原因无法获取监视器,它将挂起,可能永远挂起。在等待监视器时,线程是不可中断的,并且不会引发文档中

通过运行测试程序和查看源代码,很明显,Sun实现的方法并不是简单地给指定的线程分配时间,而是首先尝试获取线程对象上的监视器。具体来说,该方法实现为“同步”

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

文档是否足够清晰

此外,如果线程由于某种原因无法获取监视器,它将挂起,可能永远挂起。在等待监视器时,线程是不可中断的,并且不会引发文档中描述的InterruptedException。另一方面,不清楚为什么线程不能获得监视器,除非在编程错误的情况下

担心显示器上的争用是否合理

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


依赖于join()的监视器是合理的实现吗?甚至有可能以其他方式实现它吗?

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

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

import java.util.*;
公开课考试
{
公共静态void main(字符串[]args)引发异常
{
对于(int i=0;i<10;i++)
{
新线程(新线程联接程序(Thread.currentThread(),i))
.start();
}
尝试
{
睡眠(10000);
}
捕获(中断异常e){}
}
私有静态类ThreadJoiner实现可运行
{
私有最终线程threadToJoin;
int-id;
公共ThreadJoiner(线程threadToJoin,int id)
{
this.threadToJoin=threadToJoin;
this.id=id;
}
公开募捐
{
尝试
{
System.out.println(“线程”+id+
“正在等待”+新日期());
螺纹连接。连接(5000);
System.out.println(“线程”+id+
“已在“+新日期()完成等待”;
}
捕获(中断异常e){}
}
}
}

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

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

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

import java.util.*;
公开课考试
{
公共静态void main(字符串[]args)引发异常
{
对于(int i=0;i<10;i++)
{
新线程(新线程联接程序(Thread.currentThread(),i))
.start();
}
尝试
{
睡眠(10000);
}
捕获(中断异常e){}
}
私有静态类ThreadJoiner实现可运行
{
私有最终线程threadToJoin;
int-id;
公共ThreadJoiner(线程threadToJoin,int id)
{
this.threadToJoin=threadToJoin;
this.id=id;
}
公开募捐
{
尝试
{
System.out.println(“线程”+id+
“正在等待”+新日期());
螺纹连接。连接(5000);
System.out.println(“线程”+id+
“已在“+新日期()完成等待”;
}
捕获(中断异常e){}
}
}
}
如果您运行它,您将看到所有线程几乎同时开始和结束等待。如果你的担忧是有根据的,你不会像你那样“错开”结局

很明显,Sun实现的方法并不是简单地给指定的线程分配时间,而是首先尝试获取线程对象上的监视器

它不会屈服于所连接的线程,它只是等待,并假设在某个时刻线程将运行到完成。在线程上使用join()不会使它比任何其他准备运行的线程更有可能运行

  • 如果N个线程都试图加入同一个线程,并且它们都指定了相同的超时T,那么T
    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) {}
            }
        }
    }