Thread.join和Synchronized有什么区别?

我很困惑何时使用Thread.join()以及何时在multithreading应用程序中使用synchronization

根据我的说法,他们都阻止或等待执行由其他一些线程完成。
这个例子必须依次按顺序模式输出10 A,10 B和10 C:

 1 : A 2 : A 3 : A 4 : A 5 : A 6 : A 7 : A 8 : A 9 : A 10 : A 1 : B 2 : B 3 : B 4 : B 5 : B 6 : B 7 : B 8 : B 9 : B 10 : B 1 : C 2 : C 3 : C 4 : C 5 : C 6 : C 7 : C 8 : C 9 : C 10 : C ----ProGraM ENDS---- 

示例从这里开始

 class SyncTest extends Thread { StringBuffer sb; public SyncTest(StringBuffer sb) { this.sb = sb; } public void run() { synchronized(sb) { for(int i=1;i<=10;i++){ System.out.println(i+" : "+sb.charAt(0)); } sb.setCharAt(0, (char) (sb.charAt(0)+1)); } } public static void main(String [] args) throws InterruptedException { StringBuffer sb = new StringBuffer("A"); Thread t1=new SyncTest(sb); Thread t2=new SyncTest(sb); Thread t3=new SyncTest(sb); t1.start(); t2.start(); t3.start(); Thread.sleep(1000); System.out.println("----ProGraM ENDS----"); } } 

在这里,输出结果是10 A,然后是10 B,接着是10 C,按顺序排列。 但我也可以使用Thread.join而不是synchronized块来获得相同的输出:

 public void run() { //removed synchronized statement... for(int i=1;i<=10;i++){ System.out.println(i+" : "+sb.charAt(0)); } sb.setCharAt(0, (char) (sb.charAt(0)+1)); } public static void main(String [] args) throws InterruptedException { StringBuffer sb = new StringBuffer("A"); Thread t1=new SyncTest(sb); Thread t2=new SyncTest(sb); Thread t3=new SyncTest(sb); t1.start(); t1.join(); t2.start(); // wait for t1 to complete t2.join(); t3.start(); // wait for t2 to complete t3.join(); // wait for t3 to complete System.out.println("----ProGraM ENDS----"); } 

任何人都可以清楚我对使用这两种技术的困惑,即何时使用Thread.join以及何时在Java上使用multithreadingsynchronization

Thread.join()等待线程完全完成,而synchronized块可用于防止两个线程同时执行同一段代码。

一般来说,很难建议何时使用一个,因为它们用于不同的目的。 很难找到一个例子,例如你的代码,两者之间的差异很小。

话虽这么说,在你的第一个例子中,不能保证输出将按字母顺序排列。 您无法确定哪个线程将首先进入synchronized块。 所以在这种特殊情况下, join()是最合适的。

thread.join()停止执行当前线程,直到连接的线程完成..你已正确评论.. 🙂

同步可防止多个线程在同一实例上执行代码的同步部分。

synchronized关键字启用锁定机制,允许线程不相互踩踏。 Java文档将此描述为“防止线程干扰和内存一致性错误”的方法。

如果使用join() ,它确保一旦线程调用join,当前线程(正在运行的线程)将不会执行,除非您调用join的线程已完成。 我认为下面的图表可能有助于更好地将其可视化。

在此处输入图像描述

资源

没有join()线程并行运行并依赖于OS时间片(首先启动)。 使用join()线程串行运行。 例如:假设你有两个调用join()方法的线程

 MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); t1.join(); // this will be start first. t2.join(); // this will be start only after above. 

现在没有join()方法, t1t2任何一个都可以先启动。 没有保证。

synchronized语句/关键字用于监视线程,因此一次只有一个线程可以访问该同步的方法/变量。 无论你是否使用join()都没关系。

如果使用synchronized with join() ,则可以保证线程t1只能先访问。 如果没有synchronizedt1t2线程都可以随时访问,但这些线程会启动并死掉。 因为join()而连续出现。

它们显然不相同,但是,如果它们将用于相同的目的(序列化访问/执行),那么同步块可以被认为是比使用连接更灵活的版本,因为它的使用与特定的线程实例无关。你想序列化执行。

此外,在同步块中,共享数据块概念比连接更加强调。

简单的例子:

你有一个静态字符串表,其中一些线程将放置一些值。 该表初始化为“empty”。 使用静态索引访问该表。 如果线程放置一个值,它将增加静态索引。

如果您同步线程,它将确保线程放置的任何值都不能被另一个线程覆盖。

如果你在线程上使用连接,只有第一个连接线程有机会将值放在表中。另一个将等待但是知道索引递增后它们将无法访问该表(空指针exception) 。 所以Join使另一个线程变得毫无用处。

此示例在包含synchronized方法的同一实例上使用线程。