方式
- 繼承Thread類
- 實現Runnable方法
實例
#繼承Thread類
public class ThreadTest2 extends Thread { private int threadCnt = 10; @Override public void run() { while (true) { if (threadCnt > 0) { System.out.println(Thread.currentThread().getName() + " 剩余個數 " + threadCnt); threadCnt--; try { Thread.sleep(30); } catch (InterruptedException e) { e.printStackTrace(); } } else { break; } } } public static void main(String[] args) { new ThreadTest2().start(); new ThreadTest2().start(); } }
執行
Thread-1 剩余個數 10 Thread-0 剩余個數 10 Thread-0 剩余個數 9 Thread-1 剩余個數 9 Thread-0 剩余個數 8 Thread-1 剩余個數 8 Thread-0 剩余個數 7 Thread-1 剩余個數 7 Thread-1 剩余個數 6 Thread-0 剩余個數 6 Thread-1 剩余個數 5 Thread-0 剩余個數 5 Thread-1 剩余個數 4 Thread-0 剩余個數 4 Thread-1 剩余個數 3 Thread-0 剩余個數 3 Thread-0 剩余個數 2 Thread-1 剩余個數 2 Thread-0 剩余個數 1 Thread-1 剩余個數 1
#實現Runnable方法
public class RunnalbleTest2 implements Runnable { private int threadCnt = 10; @Override public void run() { while (true) { if (threadCnt > 0) { System.out.println(Thread.currentThread().getName() + " 剩余個數 " + threadCnt); threadCnt--; try { Thread.sleep(30); } catch (InterruptedException e) { e.printStackTrace(); } } else { break; } } } public static void main(String[] args) { RunnalbleTest2 runnalbleTest2 = new RunnalbleTest2(); new Thread(runnalbleTest2).start(); new Thread(runnalbleTest2).start(); new Thread(runnalbleTest2).start(); new Thread(runnalbleTest2).start(); } }
執行
Thread-0 剩余個數 10 Thread-1 剩余個數 10 Thread-2 剩余個數 8 Thread-3 剩余個數 7 Thread-1 剩余個數 6 Thread-3 剩余個數 5 Thread-2 剩余個數 6 Thread-0 剩余個數 6 Thread-1 剩余個數 2 Thread-0 剩余個數 2 Thread-2 剩余個數 2 Thread-3 剩余個數 2
可以看出該實例中雖然是2個線程,但操作的threadCnt卻是一個,實現了資源共享。
比較
實現接口的方式比繼承類的方式更靈活,也能減少程序之間的耦合度,面向接口編程也是設計模式6大原則的核心
start()方法和run()方法區別
涉及到線程的幾個狀態
新建狀態:使用 new 關鍵字和 Thread 類(或其子類)建立一個線程對象后,該線程對象就處於新建狀態。它保持這個狀態直到程序 start() 這個線程。
就緒狀態:當線程對象調用了start()方法之后,該線程就進入就緒狀態。就緒狀態的線程處於就緒隊列中,要等待JVM里線程調度器的調度。
運行狀態:如果就緒狀態的線程獲取到 CPU 資源,就可以執行 run(),此時線程便處於運行狀態。處於運行狀態的線程最為復雜,它可以變為阻塞狀態、就緒狀態和死亡狀態。
區別
只有調用了start()方法,才會表現出多線程的特性,不同線程的run()方法里面的代碼交替執行。如果只是調用run()方法,那么代碼還是同步執行的,必須等待一個線程的run()方法里面的代碼全部執行完畢之后,另外一個線程才可以執行其run()方法里面的代碼。測試如下
package com.jihite.helloworld.thread; public class TestNoStart { public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread() { @Override public void run() { pong(1); try { Thread.sleep(7000); } catch (InterruptedException e) { e.printStackTrace(); } } }; Thread t2 = new Thread() { @Override public void run() { pong(2); try { Thread.sleep(7000); } catch (InterruptedException e) { e.printStackTrace(); } } }; t1.start(); t2.start(); // t1.run(); // t2.run(); System.out.println("ping~~~~"); } static void pong(int i) { System.out.println("pong~" + i); } }
參考