繁体   English   中英

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

[英]Java Thread synchronization - Thread.sleep() Method Not Working as desired

我听说,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副本。

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

为了模拟,修改Thread1Thread2接受的一个实例Syncc

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();
}

睡眠,产量和加入规则

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

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

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

  • 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方法线程正在调用它自己的函数副本。 由于两个线程只在它们的副本上起作用,因此它就像一个单线程场景。 如果您确实想测试多线程场景,那么请将该方法设为静态(类级方法)并应用类级锁。

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();
        }
    }
}

}}

暂无
暂无

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

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