Java多線程

線程概念

一:程序 進程 線程
  1. 程序:Program 編寫的代碼,指令集,靜態概念
  2. 進程:Process 操作系統調度程序,動態概念  作爲資源分配的單位
  3. 線程:Thread 進程內多條執行路徑 輕量級進程 調度和執行的單位 線程使用的資源是它所屬進程的資源 只能共享資源 除CPU外不會爲線程分配內存

線程創建

一:繼承Thread + 重寫run()方法
Rabbit.java
public class Rabbit extends Thread {
	public void run() {
		for(int i=0; i<5; i++) {
			System.out.println("Rabbit: " + i);
		}
	}
}
啓動:創建子類對象 + 調用子類對象.start()方法
RabbitApp.java
public class RabbitApp {

	public static void main(String[] args) {
		Rabbit rabbit = new Rabbit();
		//Tortoise tortoise = new Tortoise();
		rabbit.start();
		//tortoise.start();
	}
}
二:實現Runnable接口 + 重寫run()方法
Programmer.java
public class Programmer implements Runnable {

	@Override
	public void run() {
		for(int i=0; i<5; i++) {
			System.out.println("Programmer: " + i);
		}
	}
}
啓動:創建真實角色
       創建代理角色:Thread + 對真實角色的引用
       代理角色.start()

ProgrammerApp.java

public class ProgrammerApp {

	public static void main(String[] args) {
		Programmer programmer = new Programmer();
		Thread proxy = new Thread(programmer);
		proxy.start();

		//for(int i=0; i<5; i++) {
		//	System.out.println("main: " + i);
		//}
	}
}

推薦:使用接口

  1. 避免單繼承侷限性
  2. 便於共享資源

三:創建Callable實現類 + 重寫call()方法 可以拋檢查時異常 前面的run()方法是不能拋異常的

線程狀態

一:線程狀態轉換圖


新生狀態:用new關鍵字和Thread類或其子類建立一個線程對象後,該線程對象就處於新生狀態。處於新生狀態的線程有自己的內存空間,通過調用start方法進入就緒狀態(runnable)
就緒狀態:處於就緒狀態的線程已經具備了運行條件,但還沒有分配到CPU,處於線程就緒隊列,等待系統爲其分配CPU。等待狀態並不是執行狀態,當系統選定一個等待執行的Thread對象後,它就會從等待執行狀態進入執行狀態,系統挑選的動作稱之爲”CPU調度“。一旦獲得CPU,線程就進入運行狀態並自動調用自己的run方法。
運行狀態:在運行狀態的線程執行自己的run方法中,代碼直到調用其他方法而終止,或等待某資源而阻塞或完成任務而死亡。如果過在給定的時間片內沒有執行結束,就會被系統給換下來回到等待執行狀態。
運行狀態:處於就緒狀態的線程獲得CPU時間片後,進入運行狀態,真正開始執行run方法。
阻塞狀態:處於運行狀態的線程在某些情況下,如執行了sleep(睡眠)方法,或等待I/O設備等資源,將讓出CPU並暫時停止自己的運行,進入阻塞狀態。在阻塞狀態的線程不能進入就緒隊列。只有當引起阻塞的原因消除時,如睡眠時間已到,或等待的I/O設備空閒下來,線程便轉入就緒狀態,重新到就緒隊列中排隊等待,被系統選中後從原來停止的位置開始繼續執行。
死亡狀態:死亡狀態是線程生命週期中的最後一個階段。線程死亡的原因有兩個。一個是正常運行的線程完成了它的全部工作;另一個是線程被強制性的終止,如通過執行stop或destroy方法來終止一個線程【不推薦使用這兩個方法。前者會產生異常,後者是強制終止,不會釋放鎖。】

停止線程

一:自然終止 線程體自然執行完畢
二:外部干涉
  1. 線程體中定義線程體使用的標識
  2. 線程體使用該標識
  3. 提供對外的方法改變該標識
  4. 外部根據條件調用該方法即可
StopDemo01.java
public class StopDemo01 {

	public static void main(String[] args) {
		Study study = new Study();
		Thread thread = new Thread(study);
		thread.start();
		for(int i=0; i<100; i++) {
			if(i==50) {
				study.stop();
			}	
			System.out.println("main thread->" + i);
		}
	}
	
}
class Study implements Runnable {
	private boolean flag = true;
	
	public void run() {
		while(flag) {
			System.out.println("study thread...");
		}
	}
	
	public void stop() {
		this.flag = false;
	}
}


線程阻塞

一:join 合併線程
JoinDemo01.java
public class JoinDemo01 extends Thread {

	public static void main(String[] args) throws Exception {
		JoinDemo01 joindemo01 = new JoinDemo01();
		Thread t = new Thread(joindemo01);
		t.start();
		
		for(int i=0; i<100; i++) {
			if(i==50) {
				t.join(); //main阻塞
			}
			System.out.println("main thread..." + i);
		}
	}

	public void run() {
		for(int i=0; i<100; i++) {
			System.out.println("join thread..." + i);
		}
	}
}<strong>
</strong>
二:yield 暫停自己的線程 static
YeildDemo01.java
public class YieldDemo01 extends Thread {

	public static void main(String[] args) {
		JoinDemo01 joindemo01 = new JoinDemo01();
		Thread t = new Thread(joindemo01);
		t.start();
		
		for(int i=0; i<100; i++) {
			if(i%10==0) {
				Thread.yield(); //暫停本線程main
			}
			System.out.println("main thread..." + i);
		}
	}

	public void run() {
		for(int i=0; i<100; i++) {
			System.out.println("yield thread..." + i);
		}
	}
}
三:sleep 休眠,不釋放鎖 static
  1. 與時間相關:倒計時
  2. 模擬網絡延時
SleepDemo01.java
public class SleepDemo01 {

	public static void main(String[] args) throws Exception {

		int num = 10;
		while(num>=0) {
			Thread.sleep(1000);
			System.out.println(num);
			num--;
		}
	}
}

線程基本信息

Thread.currentThread() //當前線程 static
setName() //設置名稱
getName() //獲取名稱
isAlive() //判斷狀態
優先級:概率大小,不是絕對的先後順序
setPriority() //設置優先級大小
getPriority() //獲取優先級

MyThready.java

public class MyThread implements Runnable {
	private boolean flag = true;
	private int num = 0;
	
	public void run() {
		while(flag) {
			System.out.println(Thread.currentThread().getName() + "->" + num);
			num++;
		}
	}
	
	public void stop() {
		this.flag = !this.flag;
	}
}
InfoDemo01.java
public class InfoDemo01 {

	public static void main(String[] args) throws Exception {
		MyThread mythread = new MyThread();
		Thread proxy = new Thread(mythread);
		proxy.setName("test");
		
		System.out.println(proxy.getName());
		System.out.println(Thread.currentThread().getName());
		
		proxy.start();
		Thread.sleep(100);
		mythread.stop();
	}
}
InfoDemo02.java
package com.cho3en1.thread.info;

public class InfoDemo02 {

	public static void main(String[] args) throws Exception {
		MyThread mythread1 = new MyThread();
		MyThread mythread2 = new MyThread();
		
		Thread t1 = new Thread(mythread1);
		Thread t2 = new Thread(mythread2);
		
		t1.setPriority(Thread.MAX_PRIORITY);
		t2.setPriority(Thread.MIN_PRIORITY);
		
		t1.start();
		t2.start();
		
		Thread.sleep(200);
		mythread1.stop();
		mythread2.stop();
	}

<h2>}</h2>

線程同步與鎖定

同步:併發 多個線程訪問同一份資源 確保資源安全 
synchronized -> 同步

一:同步塊
synchronized(引用類型|this|類.class) {
}

二:同步方法
synchronized 
SynDemo01.java
public class SynDemo01 {
	
	public static void main(String[] args) {
		Web12306 w = new Web12306();
		
		Thread p1 = new Thread(w, "黃牛1");
		Thread p2 = new Thread(w, "黃牛2");
		Thread p3 = new Thread(w, "黃牛3");
		
		p1.start();
		p2.start();
		p3.start();
		
	}
}

class Web12306 implements Runnable {
	private boolean flag = true;
	private int num = 50;
	
	@Override
	public void run() {
		while(flag) {
			test1();
		}
	}
	
	public synchronized void test1() {
		if(num<=0) {
			flag = false;
			return;
		}
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName() + "搶到了" + num--);
	}
}

三:死鎖
SynDemo02.java
public class SynDemo02 {

	public static void main(String[] args) {
		Test t1 = new Test();
		Test t2 = new Test();
		t1.flag = true;
		t2.flag = false;
		Thread proxy1 = new Thread(t1);
		Thread proxy2 = new Thread(t2);
		proxy1.start();
		proxy2.start();
	}

}

class Test implements Runnable {
	public boolean flag; 
	
	static Object goods = new Object();
	static Object money = new Object();
	
	public void run() {
		while(true) {
			test();
		}
	}
	
	public void test() {
		if(flag == true) {
			synchronized (goods) {
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				synchronized (money) {
					System.out.println("一手給錢");
				}
			}	
		}
		if(flag == false) {
			synchronized (money) {
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				synchronized (goods) {
					System.out.println("一手給貨");
				}
			}
		}
	}
}



發佈了10 篇原創文章 · 獲贊 3 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章