Java核心知识点 --- 线程中如何创建锁和使用锁 Lock , 设计一个缓存系统
理論知識(shí)很枯燥,但這些都是基本功,學(xué)完可能會(huì)忘,但等用的時(shí)候,會(huì)發(fā)覺(jué)之前的學(xué)習(xí)是非常有意義的,學(xué)習(xí)線程就是這樣子的.?
1.如何創(chuàng)建鎖?
Lock lock = new ReentrantLock();
2.如何使用鎖?
可以參看Lock文檔,其使用格式如下:
class X {private final ReentrantLock lock = new ReentrantLock();// ...public void m() {lock.lock(); // block until condition holdstry {// ... method body} finally {lock.unlock()}}}在要用的方法前加上鎖,比如寫(xiě)操作,然后在finally中將鎖打開(kāi).
這里,將前文java核心知識(shí)點(diǎn)學(xué)習(xí)----多線程并發(fā)之線程同步中的代碼改用Lock實(shí)現(xiàn)數(shù)據(jù)同步,改寫(xiě)代碼如下:
package com.amos.concurrent;import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock;/*** @ClassName: LockTest* @Description: Lock學(xué)習(xí)* @author: amosli* @email:hi_amos@outlook.com* @date Apr 22, 2014 1:48:36 AM*/ public class LockTest {public static void main(String[] args) {new LockTest().init();}private void init() {final OutPuter outPuter = new OutPuter();// 新建一個(gè)線程new Thread(new Runnable() {public void run() {while (true) {// 休息10mstry {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}outPuter.output("hi_amos");// 輸出}}}).start();new Thread(new Runnable() {public void run() {while (true) {try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}outPuter.output("amosli");}}}).start();}static class OutPuter {// 方式1:使用synchronized關(guān)鍵字// public synchronized void output(String name) {// int length = name.length();// for (int i = 0; i < length; i++) {// System.out.print(name.charAt(i));// }// System.out.println();// }// 方式2:使用Lock鎖Lock lock = new ReentrantLock();public void output(String name) {lock.lock();// 加鎖int length = name.length();// 輸出name,逐個(gè)字節(jié)讀取,并輸出try {for (int i = 0; i < length; i++) {System.out.print(name.charAt(i));}System.out.println();} finally {lock.unlock();// 解鎖}}} }3.synchronized關(guān)鍵字與Lock的區(qū)別?
1).Lock是Java5中的新特性,更加面向?qū)ο?更類(lèi)似于生活中的鎖.
2).Lock鎖一般需要手動(dòng)開(kāi)啟和關(guān)閉,而synchronized則不需要.
建議優(yōu)先使用Lock.
4.注意事項(xiàng):
1)多個(gè)讀鎖不互斥,讀鎖與寫(xiě)鎖互斥,寫(xiě)鎖與寫(xiě)鎖互斥.
2)要實(shí)現(xiàn)兩個(gè)線程互斥,那么要將鎖加到同一個(gè)被訪問(wèn)對(duì)象上.
3)如果你的代碼修改數(shù)據(jù),只能有一個(gè)人在寫(xiě),且不能同時(shí)讀取,那就上寫(xiě)鎖,總之,讀的時(shí)候用讀鎖,寫(xiě)的時(shí)候用寫(xiě)鎖!
?
5.設(shè)計(jì)一個(gè)緩存系統(tǒng)
什么是緩存系統(tǒng)??就是看本地是否已經(jīng)緩存過(guò)此數(shù)據(jù),如果已經(jīng)緩存過(guò),那就直接拿來(lái)用;如果沒(méi)有緩存過(guò),那就查詢(xún)數(shù)據(jù)庫(kù).
下面看代碼:
private Map<String, Object> cache = new HashMap<String, Object>();public synchronized Object getData(String key){Object object = cache.get(key);if (object==null) {object = "1323";//實(shí)際是去queryDB();}return object;}這里其實(shí)是一個(gè)超級(jí)簡(jiǎn)單的緩存系統(tǒng),原理就是:第一次訪問(wèn)的時(shí)候把值存入到cache中,第二次訪問(wèn)時(shí),先去看cache中是否有值如果有值,那么就直接去取值,而不是從數(shù)據(jù)庫(kù)中去取.
為什么要加上synchronized? 這是為了保持?jǐn)?shù)據(jù)互斥,訪問(wèn)的時(shí)候不相互影響,因?yàn)槠渲杏袑?duì)object進(jìn)行賦值操作,這是一個(gè)寫(xiě)操作,所以最好加上鎖.
如何優(yōu)化?
private ReadWriteLock rwl = new ReentrantReadWriteLock();public synchronized Object getData(String key){rwl.readLock();//read lockObject object = cache.get(key);try{if (object==null) {rwl.readLock().unlock();//釋放鎖rwl.writeLock().lock();//對(duì)寫(xiě)加鎖try{object = "1323";//實(shí)際是去queryDB();}finally{rwl.writeLock().unlock();}}}finally{rwl.readLock().unlock();}return object;}?
上面的代碼運(yùn)用到了剛學(xué)到的知識(shí),對(duì)所有讀和寫(xiě)進(jìn)行加鎖,以保持線程間的互斥,要特別注意的是要在finally中把鎖打開(kāi),不管程序是否執(zhí)行成功,因?yàn)槿绻唤怄i,那么程序?qū)?huì)產(chǎn)生死鎖,關(guān)于死鎖,將在接下來(lái)的文章中介紹.
轉(zhuǎn)載于:https://www.cnblogs.com/ncy1/p/9164474.html
總結(jié)
以上是生活随笔為你收集整理的Java核心知识点 --- 线程中如何创建锁和使用锁 Lock , 设计一个缓存系统的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: javaee_SSH
- 下一篇: RPC远程过程