本篇內(nèi)容主要講解“jdk中ReentrantLock類與Condition類結(jié)合的使用方法”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“jdk中ReentrantLock類與Condition類結(jié)合的使用方法”吧!
創(chuàng)新互聯(lián)始終致力于在企業(yè)網(wǎng)站建設(shè)領(lǐng)域發(fā)展。秉承“創(chuàng)新、求實(shí)、誠(chéng)信、拼搏”的企業(yè)精神,致力為企業(yè)提供全面的網(wǎng)絡(luò)宣傳與技術(shù)應(yīng)用整體策劃方案,為企業(yè)提供包括“網(wǎng)站建設(shè)、響應(yīng)式網(wǎng)站建設(shè)、手機(jī)網(wǎng)站建設(shè)、微信網(wǎng)站建設(shè)、小程序定制開發(fā)、購(gòu)物商城網(wǎng)站建設(shè)、平臺(tái)網(wǎng)站建設(shè)秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。
我們?cè)谏弦黄?jiǎn)單介紹了ReentrantLock類的基本使用,也就是獲取鎖,與釋放鎖。那如果我們要實(shí)現(xiàn)wait()和notify()等待通知的功能在ReentrantLock類中我們應(yīng)該怎么辦呢。這時(shí)我們就要借助一個(gè)新類了,它就是Condition類。Condition類也是JDK1.5以后新增的類。它可以實(shí)現(xiàn)多路通知功能,也就是說(shuō)在一個(gè)Lock對(duì)象中可以創(chuàng)建多個(gè)Condition類相當(dāng)于有多個(gè)鎖對(duì)象,通知的時(shí)候可以選擇性的進(jìn)行線程通知,而不是notify()那樣是由CPU隨機(jī)決定通知的是哪個(gè)線程,Condition類使它在線程調(diào)度上更加靈活。下面我們看一下具體的事例。
/**
* 用戶登錄
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:35
* @since 1.0.0
*/
public class Userinfo {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void await() {
try {
lock.lock();
System.out.println(String.format("線程開始\tthread: %s", Thread.currentThread().getName()));
condition.await();
System.out.println(String.format("線程結(jié)束\tthread: %s", Thread.currentThread().getName()));
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void signal() {
lock.lock();
System.out.println(String.format("線程恢復(fù)\tthread: %s", Thread.currentThread().getName()));
condition.signal();
lock.unlock();
}
}
/**
* 管理用戶請(qǐng)求
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:44
* @since 1.0.0
*/
public class RequestAdmin extends Thread {
private Userinfo userinfo;
public RequestAdmin(Userinfo userinfo) {
this.userinfo = userinfo;
}
@Override
public void run() {
userinfo.await();
}
}
/**
* 用戶請(qǐng)求
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:44
* @since 1.0.0
*/
public class RequestUser extends Thread {
private Userinfo userinfo;
public RequestUser(Userinfo userinfo) {
this.userinfo = userinfo;
}
@Override
public void run() {
userinfo.signal();
}
}
/**
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-20 13:35
* @since 1.0.0
*/
public class Test {
public static void main(String[] args) throws InterruptedException {
Userinfo userinfo = new Userinfo();
RequestAdmin requestAdmin = new RequestAdmin(userinfo);
RequestUser requestUser = new RequestUser(userinfo);
requestAdmin.start();
Thread.sleep(1000);
for (int i = 3; i > 0; i--) {
System.out.println(String.format("倒計(jì)時(shí):%s", i));
Thread.sleep(1000);
}
requestUser.start();
}
}
線程開始 thread: Thread-0
倒計(jì)時(shí):3
倒計(jì)時(shí):2
倒計(jì)時(shí):1
線程恢復(fù) thread: Thread-1
線程結(jié)束 thread: Thread-0
我們用ReentrantLock和Condition類成功實(shí)現(xiàn)了wait()和notify()暫停與通知的功能。使用還是比較簡(jiǎn)單,和以前的wait()、notify()方法使用基本一致。
condition.await(); // 相當(dāng)于wait()方法
condition.signal();// 相當(dāng)于notify()方法
我們知道用notifyAll()方法可以恢復(fù)暫停的所有線程,同樣Condition類中也有同樣的方法實(shí)現(xiàn)了該邏輯,只是方法不叫notifyAll()而是叫signalAll()方法。請(qǐng)看下面事例。
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 用戶登錄
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:35
* @since 1.0.0
*/
public class Userinfo {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void await1() {
try {
lock.lock();
System.out.println(String.format("await1線程開始\tthread: %s", Thread.currentThread().getName()));
condition.await();
System.out.println(String.format("await1線程結(jié)束\tthread: %s", Thread.currentThread().getName()));
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void await2() {
try {
lock.lock();
System.out.println(String.format("await2線程開始\tthread: %s", Thread.currentThread().getName()));
condition.await();
System.out.println(String.format("await2線程結(jié)束\tthread: %s", Thread.currentThread().getName()));
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void signalAll() {
lock.lock();
System.out.println(String.format("恢復(fù)所有線程\tthread: %s", Thread.currentThread().getName()));
condition.signalAll();
lock.unlock();
}
}
/**
* 管理用戶請(qǐng)求
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:44
* @since 1.0.0
*/
public class RequestAdmin extends Thread {
private Userinfo userinfo;
public RequestAdmin(Userinfo userinfo) {
this.userinfo = userinfo;
}
@Override
public void run() {
userinfo.await1();
}
}
/**
* 用戶請(qǐng)求
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:44
* @since 1.0.0
*/
public class RequestUser extends Thread {
private Userinfo userinfo;
public RequestUser(Userinfo userinfo) {
this.userinfo = userinfo;
}
@Override
public void run() {
userinfo.await2();
}
}
/**
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-20 13:35
* @since 1.0.0
*/
public class Test {
public static void main(String[] args) throws InterruptedException {
Userinfo userinfo = new Userinfo();
RequestAdmin requestAdmin = new RequestAdmin(userinfo);
RequestUser requestUser = new RequestUser(userinfo);
requestAdmin.start();
requestUser.start();
Thread.sleep(1000);
for (int i = 3; i > 0; i--) {
System.out.println(String.format("倒計(jì)時(shí):%s", i));
Thread.sleep(1000);
}
userinfo.signalAll();
}
}
await1線程開始 thread: Thread-0
await2線程開始 thread: Thread-1
倒計(jì)時(shí):3
倒計(jì)時(shí):2
倒計(jì)時(shí):1
恢復(fù)所有線程 thread: main
await1線程結(jié)束 thread: Thread-0
await2線程結(jié)束 thread: Thread-1
我們看因?yàn)檎{(diào)用了signalAll()方法,所以所有暫停的線程都被恢復(fù)了。這和notifyAll()方法一樣,沒(méi)什么好說(shuō)的。但如果我們想要實(shí)現(xiàn)恢復(fù)指定的線程那應(yīng)該怎么辦呢?我們知道調(diào)用notifyAll()方法恢復(fù)哪個(gè)線程是由CPU決定的,我們程序是控制不了的,這時(shí)有人可能會(huì)想到設(shè)置線程的優(yōu)先級(jí)來(lái)實(shí)現(xiàn)讓指定的線程優(yōu)先執(zhí)行。但這還不是絕對(duì)的。設(shè)置優(yōu)先級(jí)也是說(shuō)明那個(gè)線程獲取執(zhí)行的概率比較大,還是不能保證百分之百執(zhí)行的。雖然用notifyAll()方法沒(méi)有什么簡(jiǎn)單的辦法讓指定的線程恢復(fù)執(zhí)行,但在Condition類中確可以很方便的實(shí)現(xiàn)此功能,這也是Condition類可以實(shí)現(xiàn)多路通知功能的體現(xiàn)。下面我們來(lái)演示一下用Condition類怎么實(shí)現(xiàn)我們上述的需求。
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 用戶登錄
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:35
* @since 1.0.0
*/
public class Userinfo {
private Lock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
public void await1() {
try {
lock.lock();
System.out.println(String.format("await1線程開始\tthread: %s", Thread.currentThread().getName()));
condition1.await();
System.out.println(String.format("await1線程結(jié)束\tthread: %s", Thread.currentThread().getName()));
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void await2() {
try {
lock.lock();
System.out.println(String.format("await2線程開始\tthread: %s", Thread.currentThread().getName()));
condition2.await();
System.out.println(String.format("await2線程結(jié)束\tthread: %s", Thread.currentThread().getName()));
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void signalAll1() {
lock.lock();
System.out.println(String.format("恢復(fù)所有線程\tthread: %s", Thread.currentThread().getName()));
condition1.signalAll();
lock.unlock();
}
public void signalAll2() {
lock.lock();
System.out.println(String.format("恢復(fù)所有線程\tthread: %s", Thread.currentThread().getName()));
condition2.signalAll();
lock.unlock();
}
}
/**
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-20 13:35
* @since 1.0.0
*/
public class Test {
public static void main(String[] args) throws InterruptedException {
Userinfo userinfo = new Userinfo();
RequestAdmin requestAdmin = new RequestAdmin(userinfo);
RequestUser requestUser = new RequestUser(userinfo);
requestAdmin.start();
requestUser.start();
Thread.sleep(1000);
for (int i = 3; i > 0; i--) {
System.out.println(String.format("倒計(jì)時(shí):%s", i));
Thread.sleep(1000);
}
userinfo.signalAll1();
}
}
await1線程開始 thread: Thread-0
await2線程開始 thread: Thread-1
倒計(jì)時(shí):3
倒計(jì)時(shí):2
倒計(jì)時(shí):1
恢復(fù)所有線程 thread: main
await1線程結(jié)束 thread: Thread-0
我們看這時(shí)就實(shí)現(xiàn)了我們上述的需求。用Condition類可以喚醒我們指定的線程,確實(shí)比notify()更簡(jiǎn)單更方便。
到此,相信大家對(duì)“jdk中ReentrantLock類與Condition類結(jié)合的使用方法”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!