標籤:java
Java 5 引入的 Concurrent 併發庫軟件包中,提供了 ReentrantLock 可重入同步鎖,用來替代 synchronized 關鍵字原語,並可提供更好的性能,以及更強大的功能。使用方法也很簡單:mysql
public final ReentrantLock lock=new ReentrantLock();sql
......數據庫
try {緩存
lock.lock();安全
// 進入同步內容mybatis
....併發
} finally {oracle
lock.unlock(); // 必須在 finally 塊中解鎖,不然一旦出現異常,執行不到解鎖,則一直鎖住了。框架
}
synchronized原語和ReentrantLock在通常狀況下沒有什麼區別,可是在很是複雜的同步應用中,請考慮使用ReentrantLock,特別是遇到下面2種需求的時候。
1.某個線程在等待一個鎖的控制權的這段時間須要中斷
2.須要分開處理一些wait-notify,ReentrantLock裏面的Condition應用,可以控制notify哪一個線程
3.具備公平鎖功能,每一個到來的線程都將排隊等候
先說第一種狀況,ReentrantLock的lock機制有2種,忽略中斷鎖和響應中斷鎖,這給咱們帶來了很大的靈活性。好比:若是A、B2個線程去競爭鎖,A線程獲得了鎖,B線程等待,可是A線程這個時候實在有太多事情要處理,就是一直不返回,B線程可能就會等不及了,想中斷本身,再也不等待這個鎖了,轉而處理其餘事情。這個時候ReentrantLock就提供了2種機制,第一,B線程中斷本身(或者別的線程中斷它),可是ReentrantLock不去響應,繼續讓B線程等待,你再怎麼中斷,我全當耳邊風(synchronized原語就是如此);第二,B線程中斷本身(或者別的線程中斷它),ReentrantLock處理了這個中斷,而且再也不等待這個鎖的到來,徹底放棄。(若是你沒有了解java的中斷機制,請參考下相關資料,再回頭看這篇文章,80%的人根本沒有真正理解什麼是java的中斷,呵呵)
這裏來作個試驗,首先搞一個Buffer類,它有讀操做和寫操做,爲了避免讀到髒數據,寫和讀都須要加鎖,咱們先用synchronized原語來加鎖,以下:
public class Buffer {
private Object lock;
public Buffer() {
lock = this;
}
public void write() {
synchronized (lock) {
long startTime = System.currentTimeMillis();
System.out.println("開始往這個buff寫入數據…");
for (;;)// 模擬要處理很長時間
{
if (System.currentTimeMillis()
- startTime > Integer.MAX_VALUE)
break;
}
System.out.println("終於寫完了");
}
}
public void read() {
synchronized (lock) {
System.out.println("從這個buff讀數據");
}
}
}
接着,咱們來定義2個線程,一個線程去寫,一個線程去讀。
public class Writer extends Thread {
private Buffer buff;
public Writer(Buffer buff) {
this.buff = buff;
}
@Override
public void run() {
buff.write();
}
}
public class Reader extends Thread {
private Buffer buff;
public Reader(Buffer buff) {
this.buff = buff;
}
@Override
public void run() {
buff.read();//這裏估計會一直阻塞
System.out.println("讀結束");
}
}
好了,寫一個Main來試驗下,咱們有意先去「寫」,而後讓「讀」等待,「寫」的時間是無窮的,就看「讀」能不能放棄了。
public class Test {
public static void main(String[] args) {
Buffer buff = new Buffer();
final Writer writer = new Writer(buff);
final Reader reader = new Reader(buff);
writer.start();
reader.start();
new Thread(new Runnable() {
@Override
public void run() {
long start = System.currentTimeMillis();
for (;;) {
//等5秒鐘去中斷讀
if (System.currentTimeMillis()
- start > 5000) {
System.out.println("不等了,嘗試中斷");
reader.interrupt();
break;
}
}
}
}).start();
}
}
咱們期待「讀」這個線程能退出等待鎖,但是事與願違,一旦讀這個線程發現本身得不到鎖,就一直開始等待了,就算它等死,也得不到鎖,由於寫線程要21億秒才能完成 T_T ,即便咱們中斷它,它都不來響應下,看來真的要等死了。這個時候,ReentrantLock給了一種機制讓咱們來響應中斷,讓「讀」能伸能屈,勇敢放棄對這個鎖的等待。咱們來改寫Buffer這個類,就叫BufferInterruptibly吧,可中斷緩存。
import java.util.concurrent.locks.ReentrantLock;
public class BufferInterruptibly {
private ReentrantLock lock = new ReentrantLock();
public void write() {
lock.lock();
try {
long startTime = System.currentTimeMillis();
System.out.println("開始往這個buff寫入數據…");
for (;;)// 模擬要處理很長時間
{
if (System.currentTimeMillis()
- startTime > Integer.MAX_VALUE)
break;
}
System.out.println("終於寫完了");
} finally {
lock.unlock();
}
}
public void read() throws InterruptedException {
lock.lockInterruptibly();// 注意這裏,能夠響應中斷
try {
System.out.println("從這個buff讀數據");
} finally {
lock.unlock();
}
}
}
固然,要對reader和writer作響應的修改
public class Reader extends Thread {
private BufferInterruptibly buff;
public Reader(BufferInterruptibly buff) {
this.buff = buff;
}
@Override
public void run() {
try {
buff.read();//能夠收到中斷的異常,從而有效退出
} catch (InterruptedException e) {
System.out.println("我不讀了");
}
System.out.println("讀結束");
}
}
public class Writer extends Thread {
private BufferInterruptibly buff;
public Writer(BufferInterruptibly buff) {
this.buff = buff;
}
@Override
public void run() {
buff.write();
}
}
public class Test {
public static void main(String[] args) {
BufferInterruptibly buff = new BufferInterruptibly();
final Writer writer = new Writer(buff);
final Reader reader = new Reader(buff);
writer.start();
reader.start();
new Thread(new Runnable() {
@Override
public void run() {
long start = System.currentTimeMillis();
for (;;) {
if (System.currentTimeMillis()
- start > 5000) {
System.out.println("不等了,嘗試中斷");
reader.interrupt();
break;
}
}
}
}).start();
}
}
此次「讀」線程接收到了lock.lockInterruptibly()中斷,而且有效處理了這個「異常」。
獲取【下載地址】 QQ: 313596790 【免費支持更新】
A 代碼生成器(開發利器);所有是源碼
增刪改查的處理類,service層,mybatis的xml,SQL( mysql 和oracle)腳本, jsp頁面 都生成
就不用寫搬磚的代碼了,生成的放到項目裏,能夠直接運行
B 阿里巴巴數據庫鏈接池druid;
數據庫鏈接池 阿里巴巴的 druid。Druid在監控、可擴展性、穩定性和性能方面都有明顯的優點
C 安全權限框架shiro ;
Shiro 是一個用 Java 語言實現的框架,經過一個簡單易用的 API 提供身份驗證和受權,更安全,更可靠
D ehcache 分佈式緩存;
是一個純Java的進程內緩存框架,具備快速、精幹等特色,普遍使用的開源Java分佈式緩存