生活随笔
收集整理的這篇文章主要介紹了
多线程与高并发(一):单机高并发应该掌握的线程基础:线程状态,异常与锁等
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
多線程復習
多線程的基本概念
什么是一個線程?如何開啟一個線程?
package com
.mashibing
.juc
.c_000
;import java
.util
.concurrent
.TimeUnit
;public class T01_WhatIsThread {private static class T1 extends Thread {@Overridepublic void run() {for(int i
=0; i
<10; i
++) {try {TimeUnit
.MICROSECONDS
.sleep(1);} catch (InterruptedException e
) {e
.printStackTrace();}System
.out
.println("T1");}}}public static void main(String
[] args
) {new T1().start();for(int i
=0; i
<10; i
++) {try {TimeUnit
.MICROSECONDS
.sleep(1);} catch (InterruptedException e
) {e
.printStackTrace();}System
.out
.println("main");}}
}
面試題:請你告訴我啟動線程的三種方式
- 繼承Thread,重寫run方法
- 實現Runnable接口,重寫run方法(或Lambda表達式)
- 通過線程池來啟動(實際上也是以上兩種之一)
package com
.mashibing
.juc
.c_000
;public class T02_HowToCreateThread {static class MyThread extends Thread {@Overridepublic void run() {System
.out
.println("Hello MyThread!");}}static class MyRun implements Runnable {@Overridepublic void run() {System
.out
.println("Hello MyRun!");}}public static void main(String
[] args
) {new MyThread().start(); new Thread(new MyRun()).start(); new Thread(()->{ System
.out
.println("Hello Lambda!");}).start();}
}
Sleep Yield Join 的含義
- sleep:睡眠,當前線程暫停一段時間,讓給別的線程去執行。睡眠時間到,自動復活
- yield:當前線程正在執行的時候,停下來進入等待隊列,回到等待隊列里。系統調度算法去決定哪個線程繼續運行(有可能還是自己)
- join:在自己當前線程加入你調用的join線程,本線程等待等調用的線程運行完了,自己再去執行。(自己join自己沒有意義)
package com
.mashibing
.juc
.c_000
;public class T03_Sleep_Yield_Join {public static void main(String
[] args
) {
testJoin();}static void testSleep() {new Thread(()->{for(int i
=0; i
<100; i
++) {System
.out
.println("A" + i
);try {Thread
.sleep(500);} catch (InterruptedException e
) {e
.printStackTrace();}}}).start();}static void testYield() {new Thread(()->{for(int i
=0; i
<100; i
++) {System
.out
.println("A" + i
);if(i
%10 == 0) Thread
.yield();}}).start();new Thread(()->{for(int i
=0; i
<100; i
++) {System
.out
.println("------------B" + i
);if(i
%10 == 0) Thread
.yield();}}).start();}static void testJoin() {Thread t1
= new Thread(()->{for(int i
=0; i
<100; i
++) {System
.out
.println("A" + i
);try {Thread
.sleep(500);} catch (InterruptedException e
) {e
.printStackTrace();}}});Thread t2
= new Thread(()->{try {t1
.join();} catch (InterruptedException e
) {e
.printStackTrace();}for(int i
=0; i
<100; i
++) {System
.out
.println("A" + i
);try {Thread
.sleep(500);} catch (InterruptedException e
) {e
.printStackTrace();}}});t1
.start();t2
.start();}
}
線程狀態
如何關閉線程?
不要使用stop()關閉線程,要讓線程自己去結束。
package com
.mashibing
.juc
.c_000
;public class T04_ThreadState {static class MyThread extends Thread {@Overridepublic void run() {System
.out
.println(this.getState());for(int i
=0; i
<10; i
++) {try {Thread
.sleep(500);} catch (InterruptedException e
) {e
.printStackTrace();}System
.out
.println(i
);}}}public static void main(String
[] args
) {Thread t
= new MyThread();System
.out
.println(t
.getState());t
.start();try {t
.join();} catch (InterruptedException e
) {e
.printStackTrace();}System
.out
.println(t
.getState());}
}
Interrupt 的含義
當 catch 到 InterruptedException 時,應該在邏輯中寫好處理方式:讓線程停止或者繼續運行
Syncronized 復習
給一個變量/一段代碼加鎖的含義是:線程拿到鎖之后,才能修改一個變量/執行一段代碼
package com
.mashibing
.juc
.c_001
;public class T {private int count
= 10;private Object o
= new Object();public void m() {synchronized(o
) { count
--;System
.out
.println(Thread
.currentThread().getName() + " count = " + count
);}}
}
package com
.mashibing
.juc
.c_002
;public class T {private int count
= 10;public void m() {synchronized(this) { count
--;System
.out
.println(Thread
.currentThread().getName() + " count = " + count
);}}
}
package com
.mashibing
.juc
.c_003
;public class T {private int count
= 10;public synchronized void m() { count
--;System
.out
.println(Thread
.currentThread().getName() + " count = " + count
);}
}
package com
.mashibing
.juc
.c_004
;public class T {private static int count
= 10;public synchronized static void m() { count
--;System
.out
.println(Thread
.currentThread().getName() + " count = " + count
);}public static void mm() {synchronized(T
.class) { count
--;}}
}
測試將syncronized方法和非syncronized方法一起調用:非syncronized方法并沒有被阻塞
package com
.mashibing
.juc
.c_007
;public class T {public synchronized void m1() { System
.out
.println(Thread
.currentThread().getName() + " m1 start...");try {Thread
.sleep(10000);} catch (InterruptedException e
) {e
.printStackTrace();}System
.out
.println(Thread
.currentThread().getName() + " m1 end");}public void m2() {try {Thread
.sleep(5000);} catch (InterruptedException e
) {e
.printStackTrace();}System
.out
.println(Thread
.currentThread().getName() + " m2 ");}public static void main(String
[] args
) {T t
= new T();new Thread(t
::m1
, "t1").start();new Thread(t
::m2
, "t2").start(); }
}
示例:臟讀
package com
.mashibing
.juc
.c_008
;import java
.util
.concurrent
.TimeUnit
;public class Account {String name
;double balance
;public synchronized void set(String name
, double balance
) {this.name
= name
;try {Thread
.sleep(2000);} catch (InterruptedException e
) {e
.printStackTrace();}this.balance
= balance
;}public double getBalance(String name
) {return this.balance
;}public static void main(String
[] args
) {Account a
= new Account();new Thread(()->a
.set("zhangsan", 100.0)).start();try {TimeUnit
.SECONDS
.sleep(1);} catch (InterruptedException e
) {e
.printStackTrace();}System
.out
.println(a
.getBalance("zhangsan"));try {TimeUnit
.SECONDS
.sleep(2);} catch (InterruptedException e
) {e
.printStackTrace();}System
.out
.println(a
.getBalance("zhangsan"));}
}
總結
以上是生活随笔為你收集整理的多线程与高并发(一):单机高并发应该掌握的线程基础:线程状态,异常与锁等的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。