線程操作的方法

線程狀態 的圖中可以發現,在Java實現多線程的程序中,雖然Thread類實現了Runnable接口,但是操作線程的主要方法並不在Runnable接口中,而是在Thread類中。

Thread類中主要方法

方法名稱 類型 概述
public Thread(Runnable target) 構造 接收Runnable接口子類對象,實例化Thread對象
public Thread(Runnable target,String name) 構造 接收Runnable接口子類對象,實例化Thread對象,並設置線程名稱
public void run() 普通 執行線程
。。。。 。。 。。。。
public final void setDemo(boolean on) 普通 將一個線程設置成後臺運行

下面介紹幾種常用的線程操作方法。

  1. 取得和設置線程的名稱
    在Thread類中可以通過getName()方法取得線程的名稱,還可以通過setName()方法設置線程的名稱。
    線程的名稱一般在啓動線程前就設置,但是也可以爲在運行的線程設置名稱。允許兩個線程擁有相同的名稱,但應該儘量避免這種情況的發生。
    如果沒有設置線程的名稱,系統會爲其自動分配名稱。
    【取得和設置線程的名稱】
class MyThread implements Runnable{
    public void run(){
            for(int i=0;i<3;i++){   
                     System.out.println(Thread.currentThread().getName()+
                        "運行,i="+i);//取得線程的名稱
            }
    }
};
public class ThreadNameDemo{
    public static void main(String args[]){
        MyThread my=new MyThread();//定義Runnable子類對象
        new Thread(my).start();//系統自動設置線程的名稱
        new Thread(my,"線程-A").start();//手動設置線程的名稱
        new Thread(my,"線程-B").start();
        new Thread(my).start();
    }
}

運行結果:

線程-A運行,i=0
Thread-1運行,i=0
線程-B運行,i=0
線程-B運行,i=1
線程-B運行,i=2
Thread-0運行,i=0
Thread-1運行,i=1
線程-A運行,i=1
Thread-1運行,i=2
Thread-0運行,i=1
Thread-0運行,i=2
線程-A運行,i=2

從程序的運行結果中可以發現,沒有設置線程名稱的線程對象也有了名字而且都是有規律的,分別是Thread-1、Thread-0,從之前講解的static關鍵字可以知道,在Thread類中避讓存在一個static類型的屬性,用於爲線程的命名。
瞭解了以上代碼後,下面觀察以下的代碼
【觀察代碼的輸出】

class MyThread implements Runnable
{
    public void run(){
        for (int i=0;i<3 ;i++ )
        {
            //取得當前線程的名字
            System.out.println(Thread.currentThread().getName()+"運行, i="+i);
        }
    }
}
public class CurrentThreadDemo
{
    public static void main(String args[])
    {
        MyThread my=new MyThread();//定義Runnable子類對象
        new Thread(my,"線程").start();//啓動線程
        my.run();//直接使用run方法
    }
}

運行結果:

main運行, i=0
線程運行, i=0
main運行, i=1
main運行, i=2
線程運行, i=1
線程運行, i=2

在以上程序中,主方法直接通過Runnable接口的子類對象調用其中的run()方法,另外一個是通過線程對象調用start()方法啓動的,從結果中可以發現,主方法實際上也是一個線程。

另外要提醒的是,在java中所有的現車都是同時啓動的,哪個線程先搶到了CPU的資源,哪個線程就先運行。
說明:Java程序中每次裕興程序至少啓動兩個線程。 從之前的學習中可以知道,每當使用Java命令執行一個類時,實際上都會啓動一個JVM,每個JVM實際上就是在操作系統中啓動了一個進程,,Java本身具有垃圾回收機制。所以在Java運行時至少會啓動兩個線程,一個main線程,另一個就是垃圾收集線程。
2. 判斷線程是否啓動
通過前面的講解可知,通過Thread類中的start()方法通知CPU這個線程已經準備好啓動了,然後等待CUP資源,運行此線程,在Java中可以使用isAlive()方法來測試是否已經啓動而且任然在運行。
【判斷線程是否啓動】

class MyThread implements Runnable{
    public void run(){//覆寫run()方法
            for(int i=0;i<3;i++){   
                     System.out.println(Thread.currentThread().getName()+
                        "運行,i="+i);//取得線程的名稱
            }
    }
};
public class ThreadAliveDemo
{
    public static void main(String args[])
    {
        MyThread my = new MyThread();//實例化Runnable子類對象
        Thread t=new Thread(my,"線程");//實例化Thread對象
        System.out.println("線程開始執行之前--》"+t.isAlive());//判斷線程是否啓動
        t.start();//啓動線程
        System.out.println("線程開始執行之後——》"+t.isAlive());//判斷線程是否啓動
        for (int i=0;i<3 ;i++ )//循環輸出三次
        {
            System.out.println("main 運行--》"+i);
        }
        System.out.println("代碼執行之後--》"+t.isAlive());//後面的輸出結果不確定

    }
}

運行結果:

線程開始執行之前--》false
線程開始執行之後——》true
main 運行--》0
main 運行--》1
main 運行--》2
代碼執行之後--》true
線程運行,i=0
線程運行,i=1
線程運行,i=2

以上的代碼運行結果是不確定的,有可能到最後線程已經不存活了,但也有可能繼續存活,這要看哪個線程先運行。因爲線程操作的不確定性,所以當主線程結束時,那麼其他線程不會受到影響,並不會隨着主線程的結束而結束。
3. 線程的強制運行
在線程操作中,可以使用join()方法讓一個線程強制運行,線程強制運行期間,其他線程無法運行,必須等待此線程完成之後才能繼續執行。
【線程的強制運行】

class MyThread implements Runnable
{
    public void run(){
        for (int i=0;i<20 ;i++ )
        {
            System.out.println(Thread.currentThread().getName()+"運行--》"+i);
        }
    }
};
public class ThreadJoinDemo
{
    public static void main(String args[])
    {
        MyThread my=new MyThread();
        Thread t=new Thread(my,"線程");
        t.start();
        for (int j=0;j<10 ;j++ )
        {
            if (j>5)
            {
                try
                {
                    t.join();//強制t進行強制進行
                }
                catch (Exception e)
                {
                }
            }
            System.out.println("Main 線程運行-->"+j);
        }
    }
}
運行結果:
Main 線程運行-->0
線程運行--》0
Main 線程運行-->1
Main 線程運行-->2
Main 線程運行-->3
線程運行--》1
Main 線程運行-->4
線程運行--》2
Main 線程運行-->5
線程運行--》3
線程運行--》4
線程運行--》5
線程運行--》6
線程運行--》7
線程運行--》8
線程運行--》9
線程運行--》10
線程運行--》11
線程運行--》12
線程運行--》13
線程運行--》14
線程運行--》15
線程運行--》16
線程運行--》17
線程運行--》18
線程運行--》19
Main 線程運行-->6
Main 線程運行-->7
Main 線程運行-->8
Main 線程運行-->9

從上面的結果可以看出,主線程必須等待這個強制運行的線程完成之後纔會繼續執行。
4. 線程的休眠
在程序中允許一個線程進行暫時休眠,直接調用Thread.sleep()方法即可實現休眠。
【線程的休眠】

class MyThread implements Runnable
{
    public void run(){
        for (int i=0;i<5 ;i++ )
        {
            try
            {
                Thread.sleep(500);//線程休眠
            }
            catch (Exception e)
            {   
            }
            System.out.println(Thread.currentThread().getName()+"運行,i="+i);
        }
    }
};
public class ThreadSleepDemo
{
    public static void main(String args[])
    {
        MyThread my=new MyThread();//實例化對象
        new Thread(my,"線程").start();//啓動線程
    }
}

運行結果:

線程運行,i=0
線程運行,i=1
線程運行,i=2
線程運行,i=3
線程運行,i=4

以上程序在執行時,每次輸出都會間隔500ms,達到延遲操作的效果。
5. 中斷線程
當一個線程運行時,另一個線程可以通過interrupt()方法即可實現休眠。
【線程的中斷】

class MyThread implements Runnable
{
    public void run(){
        System.out.println("1、進入run方法 ");
        try
        {
            Thread.sleep(10000);//休眠10s
            System.out.println("2、已經完成休眠");
        }
        catch (Exception e)
        {
            System.out.println("3、休眠被終止了");
            return;//讓程序返回被調用處
        }
    }
}
public class ThreadInterruptDemo
{
    public static void main(String args[])
    {
        MyThread my=new MyThread();//實例化Runnable接口對象
        Thread t=new Thread(my,"線程");//實例化線程對象
        t.start();
        try
        {
            Thread.sleep(2000);//停止2S後再中斷
        }
        catch (Exception e)
        {
        }
        t.interrupt();//中斷線程
    }
}

運行結果:

1、進入run方法 
3、休眠被終止了

從以上程序運行的結果可以看出,一個線程啓動之後進入了休眠狀態,原本是休眠10s後繼續運行,但是主方法在線程啓動的2s後就將其中斷了,休眠一旦中斷,就執行catch中的代碼,並利用裏面的return語句返回程序的調用處。
6. 後臺線程
在Java程序中,只要前臺有一個線程在運行,則整個Java進程就不會消失,所以此時可以設置一個後臺線程,這樣Java進程結束了,此後臺線程依然會繼續執行。使用setDaemon()方法即可。
【後臺線程的設置】

class MyThread implements Runnable
{
    public void run(){


        while (true)//無限循環
        {
            System.out.println(Thread.currentThread().getName()+"在運行。");

        }
    }
}
public class ThreadDaemonDemo
{
    public static void main(String args[])
    {
        MyThread my=new MyThread();
        Thread t=new Thread(my,"線程");
        t.setDaemon(true);//設置爲後臺線程
        t.start();
    }
}

在線程MyThread類中,儘管run()方法中是死循環的方式,但是程序依然可以執行完,因爲方法在中死循環的線程操作已經設置爲了後臺運行了。
7. 線程的優先級
在Java的線程操作中,所有的線程在運行前都會保持在就緒狀態,那麼此時,哪個線程的優先級高,哪個線程就可能會先被執行。
線程的優先級:

Created with Raphaël 2.1.0MIN_PRIORITYNORM_PRIORITYMAX_PRIORITY

優先級越高,越有可能先執行。
在Java的線程中使用setPriority()方法可以設置一個線程的優先級,在Java的線程中一共有3中優先級:

定義 描述 表示的常量
public static final MIN_PRIORITY 最低優先級 1
public static final NORM_PRIORITY 中等優先級,線程的默認優先級 5
public static final MAX_PRIORITY 最高優先級 10

不同優先級的線程執行結果。
【測試線程優先級】

class MyThread implements Runnable
{
    public void run(){
        for (int i=0;i<5 ;i++ )
        {
            try
            {
                Thread.sleep(500);
            }
            catch (Exception e)
            {
            }
            System.out.println(Thread.currentThread().getName()+"運行,i="+i);
        }
    }
};
public class ThreadPriorityDemo
{
    public static void main(String[] args)
    {
        Thread t1=new Thread(new MyThread(),"線程A");
        Thread t2=new Thread(new MyThread(),"線程B");
        Thread t3=new Thread(new MyThread(),"線程C");
        t1.setPriority(Thread.MIN_PRIORITY);//設置優先級爲最低優先級
        t2.setPriority(Thread.MAX_PRIORITY);//設置優先級爲最高優先級
        t3.setPriority(Thread.NORM_PRIORITY);//設置優先級爲中等優先級
        t1.start();
        t2.start();
        t3.start();
    }
}

運行結果:

線程B運行,i=0
線程A運行,i=0
線程C運行,i=0
線程B運行,i=1
線程C運行,i=1
線程A運行,i=1
線程B運行,i=2
線程C運行,i=2
線程A運行,i=2
線程B運行,i=3
線程A運行,i=3
線程C運行,i=3
線程B運行,i=4
線程C運行,i=4
線程A運行,i=4

從上面的運行結果可以觀察到,線程將根據其優先級的大小來決定哪個線程會先運行,但是讀者一定要注意的是,並非線程的優先級越高就一定優先執行,哪個線程先執行將由CPU決定。
主線程的優先級是NORM_PRIORITY
8. 線程的禮讓
在線程操作中,也可以使用yield()方法將一個線程的操作暫時讓給其他線程執行。
【線程的禮讓】

class MyThread implements Runnable
{
    public void run(){
        for (int i=0;i<5 ;i++ )
        {
            System.out.println(Thread.currentThread().getName()+"運行-->"+i);
            if (i==2)
            {
                System.out.print("線程禮讓:");
                Thread.currentThread().yield();//線程禮讓
            }
        }
    }
};
public class ThreadYieldDemo
{
    public static void main(String args[])
    {
        MyThread my=new MyThread();
        Thread t1=new Thread(my,"線程A");
        Thread t2=new Thread(my,"線程B");
        t1.start();
        t2.start();
    }
}

運行結果:

線程A運行-->0
線程B運行-->0
線程B運行-->1
線程B運行-->2
線程禮讓:線程A運行-->1
線程A運行-->2
線程禮讓:線程B運行-->3
線程B運行-->4
線程A運行-->3
線程A運行-->4

從結果就可以發現,每當線程滿足條件時(i==2),就會將本線程暫停,而讓其他線程先執行。

好了,以上就是線程常用的幾種操作了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章