java線程的阻塞及喚醒
1. sleep() 方法:
sleep(…毫秒),指定以毫秒為單位的時間,使線程在該時間內進入線程阻塞狀態,期間得不到cpu的時間片,等到時間過去了,線程重新進入可執行狀態。(暫停線程,不會釋放鎖)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
//測試sleep()方法 class Thread7 implements Runnable{ @Override public void run() { for ( int i= 0 ;i< 50 ;i++){ System.out.println(Thread.currentThread().getName()+ "num=" +i); try { Thread.sleep( 500 ); } catch (InterruptedException e) { e.printStackTrace(); } } } } class Thread8 implements Runnable{ @Override public void run() { for ( int i= 0 ;i< 1000 ;i++){ System.out.println(Thread.currentThread().getName()+ "num=" +i); } } } public static void main(String[] args) { /* * 測試線程阻塞 */ //測試sleep()方法 Thread7 t7= new Thread7(); Thread8 t8= new Thread8(); Thread t81= new Thread(t8, "餃子" ); Thread t71= new Thread(t7, "包子" ); Thread t72= new Thread(t7, "面包" ); t71.start(); t81.start(); t72.start(); } |
2.suspend() 和 resume() 方法:。
掛起和喚醒線程,suspend()使線程進入阻塞狀態,只有對應的resume()被調用的時候,線程才會進入可執行狀態。(不建議用,容易發生死鎖)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
//測試suspend()和resume()方法 class Thread9 implements Runnable{ @Override public void run() { for ( long i= 0 ;i< 500000000 ;i++){ System.out.println(Thread.currentThread().getName()+ " num= " +i); } } } public static void main(String[] args) { //測試suspend和resume Thread9 t9= new Thread9(); Thread t91= new Thread(t9, "包子" ); t91.start(); try { Thread.sleep( 2000 ); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } t91.suspend(); try { Thread.sleep( 2000 ); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } t91.resume(); } |
(在控制臺打印輸出的時候,會停頓2秒鐘,然后再繼續打印。)
3. yield() 方法:
會使的線程放棄當前分得的cpu時間片,但此時線程任然處于可執行狀態,隨時可以再次分得cpu時間片。yield()方法只能使同優先級的線程有執行的機會。調用 yield() 的效果等價于調度程序認為該線程已執行了足夠的時間從而轉到另一個線程。(暫停當前正在執行的線程,并執行其他線程,且讓出的時間不可知)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
//測試yield()方法 class Thread10 implements Runnable{ @Override public void run() { for ( int i= 0 ;i< 100 ;i++){ System.out.println(Thread.currentThread().getName()+ " num= " +i); if (i== 33 ){ Thread.yield(); } } } } public static void main(String[] args) { //測試yield Thread10 t10 = new Thread10(); Thread t101= new Thread(t10, "包子" ); Thread t102= new Thread(t10, "面包" ); t101.start(); t102.start(); } /* 運行結果為: …… 包子 num= 24 包子 num= 25 包子 num= 26 包子 num= 27 包子 num= 28 包子 num= 29 包子 num= 30 包子 num= 31 包子 num= 32 包子 num= 33 面包 num= 0 面包 num= 1 面包 num= 2 面包 num= 3 …… 面包 num= 30 面包 num= 31 面包 num= 32 面包 num= 33 包子 num= 34 包子 num= 35 包子 num= 36 包子 num= 37 包子 num= 38 …… */ |
(可以看到,當數字為33時,都發生了交替。)
4.wait() 和 notify() 方法:
兩個方法搭配使用,wait()使線程進入阻塞狀態,調用notify()時,線程進入可執行狀態。wait()內可加或不加參數,加參數時是以毫秒為單位,當到了指定時間或調用notify()方法時,進入可執行狀態。(屬于Object類,而不屬于Thread類,wait( )會先釋放鎖住的對象,然后再執行等待的動作。由于wait( )所等待的對象必須先鎖住,因此,它只能用在同步化程序段或者同步化方法內,否則,會拋出異常IllegalMonitorStateException.)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
//測試wait()和notify()方法 //用生產者和消費者模式模擬這一過程 /*消費者 */ class Consumer implements Runnable { private Vector obj; public Consumer(Vector v) { this.obj = v; } public void run() { synchronized (obj) { while (true) { try { if (obj.size() == 0) { obj.wait(); } System.out.println("消費者:我要買面包。"); System.out.println("面包數: " + obj.size()); obj.clear(); obj.notify(); } catch (Exception e) { e.printStackTrace(); } } } } } /* 生產者 */ class Producter implements Runnable { private Vector obj; public Producter(Vector v) { this .obj = v; } public void run() { synchronized (obj) { while ( true ) { try { if (obj.size() != 0 ) { obj.wait(); } obj.add( new String( "面包" )); obj.notify(); System.out.println( "生產者:面包做好了。" ); Thread.sleep( 500 ); } catch (Exception e) { e.printStackTrace(); } } } } } public static void main(String[] args) { //測試wait()和notify() Vector obj = new Vector(); Thread consumer = new Thread( new Consumer(obj)); Thread producter = new Thread( new Producter(obj)); consumer.start(); producter.start(); } |
5.join()方法
也叫線程加入。是當前線程A調用另一個線程B的join()方法,當前線程轉A入阻塞狀態,直到線程B運行結束,線程A才由阻塞狀態轉為可執行狀態。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
//測試join class Thread11 implements Runnable{ @Override public void run() { System.out.println( "Start Progress." ); try { for ( int i= 0 ;i< 5 ;i++){ System.out.println( "Thread11線程 : " +i); Thread.sleep( 1000 ); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println( "End Progress." ); } } public static void main(String[] args) { //測試join Thread11 t11= new Thread11(); Thread t111= new Thread(t11); t111.start(); try { t111.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println( "hi,I'm Main線程" ); } /* 運行結果為: Start Progress. Thread11線程 : 0 Thread11線程 : 1 Thread11線程 : 2 Thread11線程 : 3 Thread11線程 : 4 End Progress. hi,I'm Main線程 */ |
總結
本文關于Java多線程阻塞與喚醒代碼示例的介紹就到這里,希望對大家學習Java有所幫助。有什么問題可以隨時留言,或者有什么方面想要了解的,您也可以留言,小編會及時給您答復。希望大家對服務器之家多多支持!
原文鏈接:http://blog.csdn.net/levi_moon/article/details/51581225