Java多執行緒3:Thread中的靜態方法

五月的倉頡發表於2015-10-01

Thread類中的靜態方法

Thread類中的靜態方法表示操作的執行緒是"正在執行靜態方法所在的程式碼塊的執行緒"。為什麼Thread類中要有靜態方法,這樣就能對CPU當前正在執行的執行緒進行操作。下面來看一下Thread類中的靜態方法:

1、currentThread()

currentThread()方法返回的是對當前正在執行執行緒物件的引用。看一個重要的例子,然後得出結論:

public class MyThread04 extends Thread
{
    static
    {
        System.out.println("靜態塊的列印:" + 
                Thread.currentThread().getName());    
    }
    
    public MyThread04()
    {
        System.out.println("構造方法的列印:" + 
                Thread.currentThread().getName());    
    }
    
    public void run()
    {
        System.out.println("run()方法的列印:" + 
                Thread.currentThread().getName());
    }
}
public static void main(String[] args)
{
    MyThread04 mt = new MyThread04();
    mt.start();
}

看一下執行結果:

靜態塊的列印:main
構造方法的列印:main
run()方法的列印:Thread-0

這個例子說明了,執行緒類的構造方法、靜態塊是被main執行緒呼叫的,而執行緒類的run()方法才是應用執行緒自己呼叫的。在這個例子的基礎上,再深入:

public class MyThread05 extends Thread
{
    public MyThread05()
    {
        System.out.println("MyThread5----->Begin");
        System.out.println("Thread.currentThread().getName()----->" + 
                Thread.currentThread().getName());
        System.out.println("this.getName()----->" + this.getName());
        System.out.println("MyThread5----->end");
    }
    
    public void run()
    {
        System.out.println("run----->Begin");
        System.out.println("Thread.currentThread().getName()----->" + 
                Thread.currentThread().getName());
        System.out.println("this.getName()----->" + this.getName());
        System.out.println("run----->end");
    }
}
public static void main(String[] args)
{
    MyThread05 mt5 = new MyThread05();
    mt5.start();
}

看一下執行結果:

MyThread5----->Begin
Thread.currentThread().getName()----->main
this.getName()----->Thread-0
MyThread5----->end
run----->Begin
Thread.currentThread().getName()----->Thread-0
this.getName()----->Thread-0
run----->end

上篇文章的開頭就說過,要理解一個重要的概念,就是"this.XXX()"和"Thread.currentThread().XXX()"的區別,這個就是最好的例子。必須要清楚的一點就是:當前執行的Thread未必就是Thread本身。從這個例子就能看出來:

(1)執行MyThread05構造方法是main,當前執行緒卻是Thread-0

(2)執行run()方法的Thread-0,當前執行緒也是Thread-0,說明run()方法就是被執行緒例項去執行的

所以,再強調一下,未必在MyThread05裡呼叫Thread.currentThread()返回回來的執行緒物件的引用就是MyThread05

2、sleep(long millis)

sleep(long millis)方法的作用是在指定的毫秒內讓當前"正在執行的執行緒"休眠(暫停執行)。這個"正在執行的執行緒"是關鍵,指的是Thread.currentThread()返回的執行緒。根據JDK API的說法,"該執行緒不丟失任何監視器的所屬權",簡單說就是sleep程式碼上下文如果被加鎖了,鎖依然在,但是CPU資源會讓出給其他執行緒。看一下例子:

public class MyThread07 extends Thread
{
    public void run()
    {
        try
        {
            System.out.println("run threadName = " + 
                    this.getName() + " begin");
            Thread.sleep(2000);
            System.out.println("run threadName = " + 
                    this.getName() + " end");
        } 
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }
}
public static void main(String[] args)
{
    MyThread07 mt = new MyThread07();
    System.out.println("begin = " + System.currentTimeMillis());
    mt.start();
    System.out.println("end = " + System.currentTimeMillis());
}

看一下執行結果:

begin = 1443694780609
end = 1443694780609
run threadName = Thread-0 begin
run threadName = Thread-0 end

當然,因為列印結果是靜態的,所以只能看出非同步執行的效果,看不出sleep(long millis)方法執行的效果。實際上第3句打出2秒後打出第4句,這和run()方法裡面的sleep(2000)是對應的

3、yield()

暫停當前執行的執行緒物件,並執行其他執行緒。這個暫停是會放棄CPU資源的,並且放棄CPU的時間不確定,有可能剛放棄,就獲得CPU資源了,也有可能放棄好一會兒,才會被CPU執行。看一下例子:

public class MyThread08 extends Thread
{
    public void run()
    {
        long beginTime = System.currentTimeMillis();
        int count = 0;
        for (int i = 0; i < 50000000; i++)
        {
            Thread.yield();
            count = count + i + 1;
        }
        long endTime = System.currentTimeMillis();
        System.out.println("用時:" + (endTime - beginTime) + "毫秒!");
    }
}
public static void main(String[] args)
{
    MyThread08 mt = new MyThread08();
    mt.start();
}

看一下執行結果:

用時:3264毫秒!
用時:3299毫秒!
用時:3232毫秒!
用時:3256毫秒!
用時:3283毫秒!
用時:3504毫秒!
用時:3378毫秒!

看到,每次執行的用時都不一樣,證明了yield()方法放棄CPU的時間並不確定。

4、interrupted()

測試當前執行緒是否已經中斷,執行後具有將狀態標識清除為false的功能。換句話說,如果連續兩次呼叫該方法,那麼返回的必定是false:

public static void main(String[] args)
{
    Thread.currentThread().interrupt();
    System.out.println("是否停止1?" + Thread.interrupted());
    System.out.println("是否停止2?" + Thread.interrupted());
    System.out.println("end!");
}

當然,這也涉及Java的中斷機制,留在後面的一篇文章專門講解。

相關文章