標籤:9.png when 基本操作 技術 結束 並發 進程 nat string
一、什麼是線程
線程是進程內的執行單元。
二、線程的基本操作2.1 狀態與操作
2.2 建立線程
Thread t1 = new Thread(new CreateThread());t1.start();# 直接覆蓋run方法# 傳target執行個體,即Runnable介面執行個體
2.3 終止線程
2.4 中斷線程
public void Thread.interrupt(); // 中斷線程public boolean Thread.isInterrupted(); // 判斷是否被中斷public static boolean Thread.interrupted(); // 判斷是否被中斷,並清除當前中斷狀態public static native void sleep(long millis) throws InterruptedException
代碼
// 線程t1public void run() { while(true) { Thread.yield(); }}// 對線程t1進行中斷操作,線程t1並不會做出響應t1.interrupt();// 執行下面這段代碼的線程,會對中斷做出響應public void run() { while(true) { if (Thread.currentThread().isInterrupted()) { System.out.println("Interrupted!"); break; } Thread.yield(); }}
sleep代碼
// 在等待的過程中,也對中斷操作做出響應public void run() { while(true) { if (Thread.currentThread().isInterrupted()) { System.out.println('Interrupted!'); break; } try { Thread.sleep(2000); } catch (InterruptedException e) { System.out.println("Interrupted When Sleep"); // 設定中斷狀態,拋出異常後會清除中斷標記位 Thread.currentThread().interrupt(); } Thread.yield(); }}
2.5 掛起和繼續執行線程
suspend()不會釋放鎖
如果加鎖發生在resume()之前,則發生死結
這兩個就法不推薦使用
類比死結:
public class BadSuspend { public static Object u = new Object(); static ChangeObjectThread t1 = new ChangeObjectThread("t1"); static ChangeObjectThread t2 = new ChangeObjectThread("t2"); public static class ChangeObjectThread extends Thread { public ChangeObjectThread(String name) { super.setName(name); } @Override public void run() { synchronized(u) { System.out.println("in " + getName()); Thread.currentThread().suspend(); } } } public static void main(String[] args) throws InterruptedException { t1.start(); Thread.sleep(100); t2.start(); t1.resume(); t2.resume(); t1.join(); t2.join(); }}
分析:
t1線程正常結束,t2線程死結
2.6 等待線程結束和謙讓
join,yeild
// 把自己佔用的CPU機會釋放掉,再和別人一起競爭CPUpublic static native void yield();// 當前線程未做完,主線程等待當前線程做完後再往下走public final void join() throws InterruptedExceptionpublic final synchronized void join(long millis) throws InterruptedException
三、守護線程
在後台默默地完成一些系統性的服務,比如記憶體回收線程、JIT線程就可以理解為守護線程
當一個Java應用內,只有守護線程時,Java虛擬機器就會自然退出
四、線程優先順序
高優先順序的線程更容易在競爭中獲勝
t1.setPriority(Thread.MAX_PRIORITY);
五、基本的線程同步操作5.1 synchronized
指定加鎖對象:對給定對象加鎖,進入同步代碼前要獲得給定對象的鎖。
直接作用於執行個體方法:相當於對當前執行個體加鎖,進入同步代碼前要獲得當前執行個體的鎖。
直接作用於靜態方法:相當於對當前類加鎖,進入同步代碼前要獲得當前類的鎖。
指定加鎖對象
public class AccountingSync implements Runnable { static AccountingSync instance = new AccountingSync(); static int i = 0; @Override public void run() { for (int j=0;j<100000;j++) { synchronized(instance) { i++; } } } public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(instance); Thread t2 = new Thread(instance); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(i); }}
作用於執行個體方法:注意多個線程要對同一個執行個體加鎖
public class AccountingSync2 implements Runnable { static AccountingSync2 instance = new AccountingSync2(); static int i = 0; public synchronized void increase() { i++; } @Override public void run() { for (int j=0;j<100000;j++) { increase(); } } public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(instance); Thread t2 = new Thread(instance); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(i); }}
作用於靜態方法:注意區別 作用於執行個體方法
5.2 wait()/notify()
notify()之後,允許線程往下走,但是如果沒有獲得鎖的話,也還是執行不了,t2.notifyAll()之後t1就可以往下執行了,但是此時t1還未獲得object鎖,必須等t2睡2秒後,獲得object鎖後執行。
Java高並發-多線程基礎