天天看點

【java多線程】線程常用操作方法總結

文章目錄

      • 線程的命名與擷取
      • 線程休眠
      • 線程中斷
      • 線程強制運作
      • 線程禮讓
      • 線程優先級

多線程的主要操作方法都在Thread類中定義了。

線程的命名與擷取

      多線的的運作狀态是不确定的,那麼在程式的開發之中為了可以擷取一些需要使用線程就隻能夠依靠線程的名字來進行操作。是以線程的名字是一個至關重要的概念,這樣在Thread類之中就提供有線程名稱的處理:

  • 構造函數:

    public Thread (Runnable target,String name);

  • 設定名字:

    public final void setName(String name);

  • 取得名字:

    public final String getName();

          對于線程對象的獲得是不可能隻是依靠一個this來完成的,因為線程的狀态不可控,但是有一點是明确的,所有的線程一定要執行run()方法,難麼這個時候可以考慮擷取目前線程,在Tread類中有擷取線程的方法:
  • 擷取目前線程:

    public static Thread currentThread();

範例: 觀察線程的命名操作

class MyThread implements Runnable {//線程主體類
    @Override
    public void run() {//線程的主體方法
        System.out.println(Thread.currentThread().getName());
    }
}
public class ThreadDemo {
    public static void main(String[] args) {
        MyThread mt  = new MyThread();
        new Thread(mt,"線程A").start();
        new Thread(mt).start();
        new Thread(mt,"線程B").start();
    }
}

           

      當開發者為線程設定名字的時候就使用這個設定的名字,而如果沒有設定名字就自動生成一個不重複的名字,這種自動的屬性命名主要是依靠static屬性完成的,在Thread類裡面有定義如下操作:

private static int threadInitNumber;
    private static synchronized int nextThreadNum() {
        return threadInitNumber++;
    }
           

範例:觀察一個程式的執行

class MyThread implements Runnable {//線程主體類
    @Override
    public void run() {//線程的主體方法
        System.out.println(Thread.currentThread().getName());
    }
}
public class ThreadDemo {
    public static void main(String[] args) {
        MyThread mt  = new MyThread();
        new Thread(mt,"線程A").start();
        mt.run();
    }
}

           

輸出結果:

main
線程A
           

      通過此時的代碼可以發現當使用了“mt.run()”直接在主方法之中調用線程類對象中的run()方法,所獲得的線程的名字為“main”,是以可以的得出一個結論:主方法也是一個線程,那麼現在的問題來了,所有的線程都是在程序上的一個劃分,那麼程序在哪裡?每當使用java指令執行程式的時候就表示啟動了一個JVM的程序,一台電腦上可以啟動若幹個JVM程序,是以JVM的程序都會有個自的線程。

【java多線程】線程常用操作方法總結

      在任何的開發之中,主線程可以建立若幹個子線程,建立子線程的目的是可以将一些複雜邏輯或者比較耗時的程式處理:

範例:子線程的處理

public class ThreadDemo {
    public static void main(String[] args) {
        System.out.println("1、執行操作任務一");
        new Thread(() -> {
            int temp = 0;
            for(int x = 0 ; x < 10 ; x ++) {
                temp += x;
                System.out.println(temp);
            }
        }).start();
        System.out.println("2、執行操作任務二");
        System.out.println("N、執行操作任務N");
    }
}
           

主線程負責處理整體流程,而子線程負責處理耗時操作。

線程休眠

      如果說現在希望某一個線程可以暫緩執行,那麼就可以使用休眠的處理,在Thread中定義的休眠方法如下:

  • 休眠:

    public static void sleep(long millis) throws InterruptedException;

  • 休眠:

    public static void sleep(long millis,int nanos)throws InterruptedException;

          在進行休眠的時候,有可能會産生中斷異常“InterruptedException”,中斷異常屬于Exception的子類,是以該異常必須進行處理。

範例: 觀察休眠處理

public class ThreadDemo {
    public static void main(String[] args) {
        new Thread(() -> {
            for(int x = 0 ; x < 10 ; x ++) {
                System.out.println(Thread.currentThread().getName() + "、x = " + x);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        },"線程對象").start();
    }
}
           

      休眠的主要特點是可以自動實作線程的喚醒,以繼續進行後續的處理。但是需要注意的是,如果現在有多個線程對象,休眠也是有多個先後順序的。

**範例:**産生多個線程對象進行休眠處理。

public class ThreadDemo {
    public static void main(String[] args) {
        for( int i = 0; i < 5; i ++) {
            new Thread(() -> {
                for(int x = 0 ; x < 10 ; x ++) {
                    System.out.println(Thread.currentThread().getName() + "、x = " + x);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
            },"線程對象 - " + i).start();
        }

    }
}
           

      此時将産生五個線程對象,并且這五個線程對象執行的方法體是相同的。此時從程式執行的感覺上來看是一起進行了休眠,而後一起進行了自動喚醒,但是實際上是有差别的。

【java多線程】線程常用操作方法總結

線程中斷

      在之前發現線程的休眠裡面提供有一個中斷異常,實際上就證明線程的休眠是可以打斷的,而這種打斷肯定是由其他線程完成的,在Thread類裡面提供有這種中斷執行的方法:

  • 判斷線程是否被中斷:

    public boolean isInterrupted();

  • 中斷線程執行:

    public void interrupt();

**範例:**觀察線程的中斷處理操作

public class ThreadDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            System.out.println("*** 狂歡了72小時我需要睡覺");
            try {
                Thread.sleep(10000);  //睡眠10秒
                System.out.println("睡足了,要繼續初五禍害别人");
            } catch (InterruptedException e) {
                System.out.println("敢打擾老子睡覺,宰了你");
            }

        });
        thread.start();
        Thread.sleep(1000);
        if( !thread.isInterrupted()) {
            System.out.println("打擾你一下");
            thread.interrupt();
        }
    }
}
           

      所有正在執行的線程都是可以被中斷的,中斷線程必須進行異常處理。

線程強制運作

      所謂的線程的強制執行,指的當滿足某些條件之後,某一個線程對象将一直可以獨占資源,一直到該線程的程式執行結束。

範例: 觀察一個沒有被強制執行的程式

public class TestThread {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
           for(int x = 0 ; x < 100 ; x ++) {
               System.out.println(Thread.currentThread().getName() + "、 x = " + x);
           }
        },"玩耍的線程");
        thread.start();
        for(int x = 0; x < 100; x ++) {
            System.out.println("【霸道的main主線程】 x = "+ x);
        }
    }
}
           

       這個時候主線程和子線程都在交替執行着,但是如果你希望主線獨占執行。那麼就是利用Thread類中方法強制執行。

  • 強制執行:

    public final void join()throws InterruptedException;

    範例: 強制執行的代碼示例
public class TestThread {
    public static void main(String[] args) {
        Thread mainThread = Thread.currentThread(); //獲得主線程
        Thread thread = new Thread(() -> {
           for(int x = 0 ; x < 100 ; x ++) {
               if(x == 3) {  //如果x == 3,就強制執行主線程
                   try {
                       mainThread.join();
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
               }
               System.out.println(Thread.currentThread().getName() + "、 x = " + x);
           }
        },"玩耍的線程");
        thread.start();
        for(int x = 0; x < 100; x ++) {
            System.out.println("【霸道的main主線程】 x = "+ x);
        }
    }
}
           

      在進行線程強制執行的時候,一定要擷取強制執行線程對象之後才可以執行join()的調用。

線程禮讓

      線程的禮讓指的是先将線程的資源讓出去,讓别的線程先執行。線程的禮讓可以使用Thread中提供的方法:

  • 禮讓:

    public static void yield();

**範例:**使用禮讓操作

public class TestThread {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            for(int x = 0 ; x < 100 ; x ++) {
                if(x % 3 == 0){
                    Thread.yield(); //線程禮讓
                    System.out.println("玩耍線程禮讓執行 ***********************");
                }
                System.out.println(Thread.currentThread().getName() + "、 x = " + x);
            }
        },"玩耍的線程");
        thread.start();
        for(int x = 0; x < 100; x ++) {
            System.out.println("【霸道的main主線程】 x = "+ x);
        }
    }
}
           

      禮讓執行的時候每一次調用yield()方法都隻會禮讓一次目前資源。

線程優先級

      從理論上來講,線程的優先級越高越有可能先執行(越有可能先搶占到資源)。在Thread類李曼針對優先級的操作有兩個操作方法:

  • 設定優先級:

    public final void setPriority(int newPriority);

  • 擷取優先級:

    public final int getPriority();

          在進行優先級定義的時候都是通過int型的數字來完成的,而對于此數字的選擇在Thread類裡面就定義有三個常量:
  • 最高優先級:

    public static final int MAX_PRIORITY;(10)

  • 中等優先級:

    public static final int NORM_PRIORITY;(5)

  • 最低優先級:

    public static final int MIN_PRIORITY;(1)

範例:觀察優先級

public class ThreadDem {
    public static void main(String[] args) {
         Runnable run = () ->{
             for(int x = 0; x < 100; x ++) {
                 System.out.println(Thread.currentThread().getName() + "、 x = " + x);
             }
         };
        Thread threadA = new Thread(run,"線程對象A");
        Thread threadB = new Thread(run,"線程對象B");
        Thread threadC = new Thread(run,"線程對象C");
        threadA.setPriority(Thread.MIN_PRIORITY);
        threadB.setPriority(Thread.MIN_PRIORITY);
        threadC.setPriority(Thread.MAX_PRIORITY);
        threadA.start();
        threadB.start();
        threadC.start();
    }
}
           

      主方法值一個主線程,那麼主線程的優先級呢?

public class ThreadDem {
    public static void main(String[] args) {
        System.out.println("預設線程的優先級:" + new Thread().getPriority());
        System.out.println("主方法線程優先級:" + Thread.currentThread().getPriority());
}
}
           

輸出結果:

預設線程的優先級:5
主方法線程優先級:5
           

**      主線程是屬于中等優先級,而預設建立的線程也是中等優先級。

**