Java线程同步 – Thread.sleep()方法不按预期工作

我听说,sleep()将锁定当前的sync方法/块但是在这里,当我在线程1上调用sleep()时,线程2能够访问同一个块吗? 谁能解释一下吗?

Main.java

public class Main { public static void main(String args[]) { Thread1 t1 = new Thread1(); Thread2 t2 = new Thread2(); System.out.println("going to start t1"); t1.start(); System.out.println("going to start t2"); t2.start(); } } 

================================================== ===================

Thread1.java

 public class Thread1 extends Thread{ public void run() { Syncc s1 = new Syncc(); s1.me("T1:"); } } 

================================================== ===================

Thread2.java

 public class Thread2 extends Thread{ public void run() { Syncc s2 = new Syncc(); s2.me("T2:"); } } 

================================================== ===================

Syncc.java

 public class Syncc{ public void me(String s){ synchronized(this){ for(int i=0; i<=5; i++) { System.out.println(s+" "+" "+i); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } } } } 

==========================================

输出:

 going to start t1 going to start t2 T2: 0 T1: 0 T2: 1 T1: 1 T1: 2 T2: 2 T1: 3 T2: 3 T1: 4 T2: 4 T2: 5 T1: 5 

但是根据sleep()方法,它不应该解锁当前的同步块吗? 如果是这样,输出应该是……

将开始t1开始t2

 T1: 0 T1: 1 T1: 2 T1: 3 T1: 4 T1: 5 T2: 0 T2: 1 T2: 2 T2: 3 T2: 4 T2: 5 

我的意思是在线程1执行后,只有线程2应该正确启动? 问题是什么?

这是因为您在这里有两个不同的Syncc实例。 每个线程都有自己的Syncc副本。

尝试对单个实例执行相同操作。 您还可以在静态上下文中进行同步并尝试。

要模拟,修改Thread2Thread2以接受Thread2的实例。

 public class Thread1 extends Thread { private Syncc syncc; public Thread1(Syncc syncc) { this.syncc = syncc; } public void run() { this.syncc.me("T1:"); } } 

然后你可以这样启动它们:

 public static void main(String args[]) { Syncc syncc = new Syncc(); Thread1 t1 = new Thread1(syncc); Thread2 t2 = new Thread2(syncc); System.out.println("going to start t1"); t1.start(); System.out.println("going to start t2"); t2.start(); } 

睡眠,产量和加入规则

  • hibernate用于延迟执行一段时间,并且当线程进入hibernate状态时不释放锁定。

  • 保证睡眠线程至少在sleep()方法的参数中指定的时间内hibernate(除非它被中断), 但不能保证新唤醒的线程何时会实际返回运行状态。

  • sleep()方法是一个静态方法,它hibernate当前正在执行的线程的状态。 一个线程无法告诉另一个线程睡眠。

  • setPriority()方法用于Thread对象,为线程提供1(低)到10(高)之间的优先级,虽然不保证优先级,并且并非所有JVM都能识别10个不同的优先级 – 某些级别可以被视为有效等于。

  • 如果未明确设置,则线程的优先级将与创建它的线程的优先级具有相同的优先级。

  • 如果存在具有相同优先级的可运行线程,则yield()方法可能会导致正在运行的线程退出。 无法保证会发生这种情况,并且无法保证在线程退出时会选择运行不同的线程。 线程可能会产生然后立即重新进入运行状态。

  • 最接近保证的是,在任何给定时间,当线程运行时,它通常不会比可运行状态中的任何线程具有更低的优先级。 如果在高优先级线程进入runnable时正在运行低优先级线程,则JVM通常会抢占正在运行的低优先级线程并将高优先级线程置于其中。

  • 当一个线程调用另一个线程的join()方法时,当前运行的线程将等待它加入的线程完成。 想想join()方法是这样说的,“嘿线程,我想加入到你的最后。让我知道你什么时候完成,所以我可以进入runnable状态。”

http://www.amazon.com/SCJP-Certified-Programmer-Java-310-065/dp/0071591060

您已创建两个Synch对象,每个对象对应一个线程。 每个对象都有自己的副本。 因此,当你启动每个线程时,使用run方法线程正在调用它自己的函数副本。 由于两个线程仅在其副本上起作用,因此其工作方式类似于单个线程场景。 如果您确实想要测试multithreading场景,那么请将该方法设为静态(类级方法)并应用类级锁。

Thread1.java

 public class Thread1 extends Thread{ public void run() { Syncc.me("T1:"); } 

}

Thread2.java

 public class Thread2 extends Thread{ public void run() { Syncc.me("T2:"); } 

}

Syncc.java

 public class Syncc{ public static void me(String s){ synchronized(Syncc.class){ for(int i=0; i<=5; i++) { System.out.println(s+" "+" "+i); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } } 

}}