Java多線程阻塞與喚醒代碼示例
java線程的阻塞及喚醒
1. sleep() 方法:
sleep(…毫秒),指定以毫秒為單位的時間,使線程在該時間內(nèi)進入線程阻塞狀態(tài),期間得不到cpu的時間片,等到時間過去了,線程重新進入可執(zhí)行狀態(tài)。(暫停線程,不會釋放鎖)
//測試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()使線程進入阻塞狀態(tài),只有對應(yīng)的resume()被調(diào)用的時候,線程才會進入可執(zhí)行狀態(tài)。(不建議用,容易發(fā)生死鎖)
//測試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秒鐘,然后再繼續(xù)打印。)
3. yield() 方法:
會使的線程放棄當(dāng)前分得的cpu時間片,但此時線程任然處于可執(zhí)行狀態(tài),隨時可以再次分得cpu時間片。yield()方法只能使同優(yōu)先級的線程有執(zhí)行的機會。調(diào)用 yield() 的效果等價于調(diào)度程序認(rèn)為該線程已執(zhí)行了足夠的時間從而轉(zhuǎn)到另一個線程。(暫停當(dāng)前正在執(zhí)行的線程,并執(zhí)行其他線程,且讓出的時間不可知)
//測試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();
}
/*
運行結(jié)果為:
……
包子 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
……
*/
(可以看到,當(dāng)數(shù)字為33時,都發(fā)生了交替。)
4.wait() 和 notify() 方法:
兩個方法搭配使用,wait()使線程進入阻塞狀態(tài),調(diào)用notify()時,線程進入可執(zhí)行狀態(tài)。wait()內(nèi)可加或不加參數(shù),加參數(shù)時是以毫秒為單位,當(dāng)?shù)搅酥付〞r間或調(diào)用notify()方法時,進入可執(zhí)行狀態(tài)。(屬于Object類,而不屬于Thread類,wait( )會先釋放鎖住的對象,然后再執(zhí)行等待的動作。由于wait( )所等待的對象必須先鎖住,因此,它只能用在同步化程序段或者同步化方法內(nèi),否則,會拋出異常IllegalMonitorStateException.)
//測試wait()和notify()方法
//用生產(chǎn)者和消費者模式模擬這一過程
/*消費者 */
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("面包數(shù): " + obj.size());
obj.clear();
obj.notify();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
/* 生產(chǎn)者 */
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("生產(chǎn)者:面包做好了。");
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()方法
也叫線程加入。是當(dāng)前線程A調(diào)用另一個線程B的join()方法,當(dāng)前線程轉(zhuǎn)A入阻塞狀態(tài),直到線程B運行結(jié)束,線程A才由阻塞狀態(tài)轉(zhuǎn)為可執(zhí)行狀態(tài)。
//測試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線程");
}
/*
運行結(jié)果為:
Start Progress.
Thread11線程 : 0
Thread11線程 : 1
Thread11線程 : 2
Thread11線程 : 3
Thread11線程 : 4
End Progress.
hi,I'm Main線程
*/
總結(jié)
本文關(guān)于Java多線程阻塞與喚醒代碼示例的介紹就到這里,希望對大家學(xué)習(xí)Java有所幫助。感興趣的朋友可以繼續(xù)參閱:Java多線程ForkJoinPool實例詳解 、 Java通過賣票理解多線程 、 Java線程安全基礎(chǔ)概念解析等。有什么問題可以隨時留言,或者有什么方面想要了解的,您也可以留言,小編會及時給您答復(fù)。希望大家對腳本之家多多支持!
相關(guān)文章
spring整合JMS實現(xiàn)同步收發(fā)消息(基于ActiveMQ的實現(xiàn))
本篇文章主要介紹了spring整合JMS實現(xiàn)同步收發(fā)消息(基于ActiveMQ的實現(xiàn)),具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-10-10
Java中一維二維數(shù)組的靜態(tài)和動態(tài)初始化
今天通過本文給大家分享Java中的數(shù)組,包括一維數(shù)組和二維數(shù)組的靜態(tài)初始化和動態(tài)初始化問題,感興趣的朋友一起看看吧2017-10-10
Java 實現(xiàn)加密數(shù)據(jù)庫連接的步驟
這篇文章主要介紹了Java 實現(xiàn)加密數(shù)據(jù)庫連接的步驟,幫助大家更好的理解和使用Java處理數(shù)據(jù)庫,感興趣的朋友可以了解下2020-11-11

