簡體   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