一、線程和進程 進程(Process): 1、是電腦中的程式關於某數據集合上的一次運行活動,是系統進行資源分配和調度的基本單位,是操作系統結構的基礎。 2、在早期面向進程設計的電腦結構中,進程是程式的基本執行實體。 3、在當代面向線程設計的電腦結構中,進程是線程的容器。程式是指令、數據及其組織 ...
一、線程和進程
進程(Process):
1、是電腦中的程式關於某數據集合上的一次運行活動,是系統進行資源分配和調度的基本單位,是操作系統結構的基礎。
2、在早期面向進程設計的電腦結構中,進程是程式的基本執行實體。
3、在當代面向線程設計的電腦結構中,進程是線程的容器。程式是指令、數據及其組織形式的描述,進程是程式的實體。
線程(thread):
1、看成是進程中的最小單元。
2、一個進程中可以有1個或者多個線程(其實也就是一小段代碼)。
3、 線程其實也可以看成是一個輕量級的進程(比如1個進程只有1個線程)。
4、在單個程式中同時運行多個線程完成不同的工作,稱為多線程。
CPU:執行任務是以線程為單位;會在不同的時間片上不斷的切換線程。
二、啟動線程兩種方式
1、啟動線程兩種方式:
1、通過繼承Thread 類
1 /** 2 * 繼承thread類 3 */ 4 public class ThreadMusic extends Thread { 5 @Override 6 public void run(){ 7 synchronized (this){ //同步 8 for (int i =0; i< 100; i ++){ 9 System.out.println(this.getName() + "------聽音樂------" + i); 10 } 11 } 12 } 13 }
2、實現 Runnable 介面
區別:一個類如果繼承了其他類,就無法在繼承Thread類,在Java中,一個類只能繼承一個類,而一個類如果實現了一個介面,還可以實現其他介面,介面是可以多實現的,所以說Runable 的擴展性更強。
1 /** 2 * 實現runnable介面 3 */ 4 public class RunnableMusic implements Runnable { 5 @Override 6 public void run() { 7 synchronized (this){ //同步 8 for (int i =0; i< 100; i ++){ 9 System.out.println(Thread.currentThread().getName() + "------聽音樂------" + i); 10 } 11 } 12 } 13 }
2、啟動線程流程:
創建啟動線程的方式一:繼承Thread類
① 明確需要把什麼事情封裝成線程對象;
② 自定義類 extends Thread類
③ 覆寫run方法: 寫①
④ 創建自定義對象t
⑤ 啟動線程 t.start();
創建啟動線程方式二:實現Runnable介面
①明確需要把什麼事情封裝成線程對象;
② 自定義類 implements Runnable介面
③ 覆寫run方法: 寫①
④ 創建自定義對象t
⑤ 啟動線程 new Thread(t).start();
測試線程:
1 public class testThread { 2 /** 3 * 測試threadMusic 4 */ 5 @Test 6 public void testThread(){ 7 ThreadMusic music = new ThreadMusic(); 8 music.start(); 9 } 10 11 /** 12 * 測試threadMusic 13 */ 14 @Test 15 public void testRunnable(){ 16 RunnableMusic runnableMusic = new RunnableMusic(); 17 Thread thread = new Thread(runnableMusic); 18 thread.start(); 19 } 20 }
3、線程方法
1、Thread類的方法
static void sleep(long millis) 在指定的毫秒數內讓當前正在執行的線程休眠(暫停執行)。
1 /** 2 * 測試sleep方法 3 */ 4 public class SleepTest{ 5 public static void main(String[] args) throws InterruptedException { 6 for(int i = 1; i<11; i++ ){ 7 System.out.println(i); 8 Thread.sleep(1000); //休眠1秒 9 } 10 } 11 }
2、獲取Thread的名稱
1 /** 2 * 繼承thread類 3 */ 4 public class ThreadMusic extends Thread { 5 @Override 6 public void run(){ 7 synchronized (this){ 8 for (int i =0; i< 100; i ++){ 9 System.out.println(this.getName() + "------聽音樂------" + i); //獲取Thread的名稱 10 } 11 } 12 } 13 }
3、獲取Runnable的名稱
1 /** 2 * 實現runnable介面 3 */ 4 public class RunnableMusic implements Runnable { 5 @Override 6 public void run() { 7 synchronized (this){ //同步 8 for (int i =0; i< 50; i ++){ 9 //獲取Runnable的名稱, currentThread()方法,返回當前正在執行的線程引用 10 System.out.println(Thread.currentThread().getName() +"------聽音樂------" + i); 11 } 12 } 13 } 14 }
結論:繼承和實現獲取線程名稱方式是不一樣。
4、Thread方法(jion)
void join() 方法 :等待該線程終止。
1 /** 2 * JoinThread線程 3 */ 4 public class JoinThread extends Thread { 5 @Override 6 public void run() { 7 for (int i = 0; i < 100; i++) { 8 System.out.println("JoinThread --->" + i); 9 try{ 10 Thread.sleep(1); //JoinThread再休眠一秒,為了交替出現更有規律 11 } catch (InterruptedException e){ 12 e.printStackTrace(); 13 } 14 } 15 } 16 }
測試 join 方法:
1 /** 2 * 測試join方法 3 */ 4 public class JoinDemo { 5 public static void main(String[] args) throws InterruptedException { 6 JoinThread joinThread = new JoinThread(); 7 joinThread.start(); 8 9 for (int i = 0; i < 100; i++) { 10 System.out.println("main ---> " + i); 11 if(i == 10){ 12 joinThread.join(); //等待該線程終止,才繼續執行main線程 13 } 14 Thread.sleep(1); //主線程模擬網路延遲 15 } 16 } 17 }
理解:joinThread.join(): 當主線程執行到10的時候,JionThread線程加進來,等待JionThread線程全部執行完,然後才繼續執行主線程。
另外除了jion()方法以外,還有jion(long millils) 方法 (等待線程執行的固定時間,然後時間一到,jion失效)。
4、線程優先順序
高優先順序線程的執行優先於低優先順序線程;並不是絕對的,可能優先順序高的線程比優先順序低的線程先執行,只能說,高優先順序的線程優先執行的幾率更多;
(比如兩個線程,一個優先順序高,一個優先順序低,如果一共運行一個小時,優先順序高的線程執行遠遠大於優先順序低的,但是並不是說,優先順序高的先執行完,在執行優先順序低的)。
方法:
int getPriority() 返回線程的優先順序
void setPriority() 更改線程的優先順序
1 public class PriorityDemo { 2 public static void main(String[] args) { 3 Thread thread = Thread.currentThread(); 4 System.out.println(thread.getPriority()); //獲取優先順序 5 thread.setPriority(8); //設置優先順序 6 System.out.println(thread.getPriority()); 7 } 8 }
自定義線程的預設優先順序和創建它的環境的線程優先順序一致。
5、守護線程
每個線程都有一個優先順序,高優先順序線程的執行優先於低優先順序線程。每個線程都可以或不可以標記為一個守護程式。
後臺線程:指為其他線程提供服務的線程,也稱為守護線程。JVM的垃圾回收線程就是一個後臺線程。
Thread類提供的方法:
方法: void setDaemon(boolean on) 將該線程標記為守護線程或用戶線程。
方法:isDaemon() 測試該線程是否為守護線程。
1 public class DaemonDemo { 2 public static void main(String[] args) { 3 //獲取主線程 4 Thread thread = Thread.currentThread(); 5 System.out.println(thread.isDaemon()); //false 非後臺線程 6 //嘗試變更為後臺線程 7 thread.setDaemon(true); 8 //活動的線程不能設置後臺線程,主線程不能設置為後臺線程。 9 System.out.println(thread.isDaemon()); //Exception in thread "main" java.lang.IllegalThreadStateException 10 } 11 }
結論::自定義線程的預設狀態和環境有關,後臺線程中創建的線程預設是後臺線程,前臺線程中創建的線程為前臺線程。
6、線程同步
Java中3種同步方式:
1、同步代碼塊
synchronized (同步監聽對象){
需要同步的代碼
}
註意事項: 同步監聽對象 可以是任意的對象,但是多個線程來訪問的,此對象必須是同一對象,一般寫this,或者當前類的位元組碼對象(類名.class),或者相關的業務對象。
2、同步方法寫法:
藉助於方法的{} 把synchronized直接作為方法的修飾符;
3、同步方式-鎖(lock)