java的concurrent包簡介
java的concurrent包中的鎖lock;工具類:CyclicBarrier、semaphore、CountDownLatch;集合:blockingquue、concurrentMap;原子量:aotmic。先從下面的圖開始,介紹下concurrent包的用法。
1、lock類
總結幾點現在知道的synchronized的異同,基本也就是個認知階段,并不能說明真實的原理資訊。以後有時間在詳細的查閱官方資料:
synchronized:
1、JVM實作
2、可以通過工具監控
3、自動釋放
4、在等待的的時候什麼都不能幹,隻有等待喚醒(jvm喚醒、打斷)
lock:
1、代碼實作、無法監控。釋放在finally裡面
2、擷取:可以明确知道結果。當然,也就可以做等待、或者直接做其他操作
3、釋放:以任何順序擷取和釋放多個鎖、釋放方式和偏向鎖類似
3、讀寫分離鎖分離
lock的實作和偏向鎖很類似,一個特點靈活,非常靈活。當然操作起來也更加困難,不過相信随着Oracle持續的釋放黑科技優化jvm,synchronized性能越來越高。
lock的使用:
public interface Lock {
//擷取鎖。如果鎖不可用,出于線程排程目的,将禁用目前線程,并且在獲得鎖之前,該線程将一直處于休眠狀态。
void lock();
//如果目前線程未被中斷,則擷取鎖
void lockInterruptibly() throws InterruptedException;
//僅在調用時鎖為空閑狀态才擷取該鎖。如果鎖可用,則擷取鎖,并立即傳回值 true。如果鎖不可用,則此方法将立即傳回值 false。
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
void unlock();
Condition newCondition();
}
其中lock的标準用法:如果拿不到鎖就在隊列中等待
Lock l = ...;
l.lock();
try {
// access the resource protected by this lock
} finally {
l.unlock();
}
tryLock的用法:如果沒有擷取鎖,可以直接做其他的用處
Lock lock = ...;
if (lock.tryLock()) {
try {
// manipulate protected state
} finally {
lock.unlock();
}
} else {
// perform alternative actions
}
lockInterruptibly:擷取一個帶有中斷處理的鎖。例如:線程A擷取了鎖,則不能中斷。線程B會一直循環,然後自旋不端擷取鎖,或者查詢是否有中斷指令。在AbstractQueuedSynchronizer源碼中,doAcquireInterruptibly(int arg)方法可以看出,是通過抛出異常來終端擷取鎖,在使用的時候需要用try。
public void testInterrupted() throws InterruptedException {
lock.lockInterruptibly();
try{
//TODO:
}finally{
lock.unlock();
}
}
例子:lock
public class lockTest implements Runnable {
private Lock lock;
public lockTest(Lock lock) {
this.lock = lock;
}
@Override
public void run() {
System.out.println("Thread Name: " + Thread.currentThread().getName() + " is begin");
lock.lock();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
System.out.println("Thread Name: " + Thread.currentThread().getName() + " is over");
lock.unlock();
}
}
public static void main(String[] args) {
Lock lock = new ReentrantLock();
// ExecutorService es = Executors.newCachedThreadPool();
for (int i = 0; i
new Thread(new lockTest(lock)).start();
;
}
// es.shutdown();
}
}
tryLock例子
public class TryLock implements Runnable {
private Lock lock;
public TryLock(Lock lock) {
this.lock = lock;
}
@Override
public void run() {
if (lock.tryLock()) {
System.out.println("Thread Name: " + Thread.currentThread().getName() + " is begin");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("Thread Name: " + Thread.currentThread().getName() + " is over");
lock.unlock();
}
} else {
System.out.println("Thread Name: " + Thread.currentThread().getName() + " is not acquire");
}
}
public static void main(String[] args) {
Lock lock = new ReentrantLock();
TryLock trylock = new TryLock(lock);
new Thread(trylock).start();
new Thread(trylock).start();
}
}
lockInterrupte:如果目前線程未被中斷,則擷取鎖。
public class LockInterrupt implements Runnable {
private Lock lock;
public LockInterrupt(Lock lock) {
this.lock = lock;
}
private void testInterrupt() {
try {
lock.lockInterruptibly();
System.out.println("Thread Name: " + Thread.currentThread().getName() + " is begin");
// Thread.sleep(5000);// 睡眠阻塞、會被打斷
//
for (;;) {
}
} catch (InterruptedException e1) {
e1.printStackTrace();
} finally {
System.out.println("Thread Name: " + Thread.currentThread().getName() + " is over");
lock.unlock();
System.out.println("Thread Name: " + Thread.currentThread().getName() + " is release");
}
}
@Override
public void run() {
this.testInterrupt();
}
public static void main(String[] args) {
try {
Lock lock = new ReentrantLock();
LockInterrupt li = new LockInterrupt(lock);
Thread t1 = new Thread(li, "t1");
Thread t2 = new Thread(li, "t2");
t1.start();
t2.start();
Thread.sleep(500);
t1.interrupt();
// t2.interrupt();// 會将t1的sleep直接打斷、然後t2
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
讀寫鎖ReentrantReadWriteLock:讀鎖可以多個線程一起使用。寫鎖隻能線程獨享,這時候還會阻塞其它讀鎖、寫鎖
public class WritReadTest {
private ReentrantReadWriteLock rrwl;
public WritReadTest(ReentrantReadWriteLock lock) {
this.rrwl = lock;
}
public void read() {
try {
rrwl.readLock().lock();
System.out.println("Thread Name: " + Thread.currentThread().getName() + " readlock is begin");
Thread.sleep(5000);// 睡眠阻塞、會被打斷
} catch (InterruptedException e1) {
e1.printStackTrace();
} finally {
System.out.println("Thread Name: " + Thread.currentThread().getName() + " readlock is over");
rrwl.readLock().unlock();
System.out.println("Thread Name: " + Thread.currentThread().getName() + " readlock is release");
}
}
public void write() {
try {
rrwl.writeLock().lock();
System.out.println("Thread Name: " + Thread.currentThread().getName() + " write is begin");
Thread.sleep(5000);// 睡眠阻塞、會被打斷
} catch (InterruptedException e1) {
e1.printStackTrace();
} finally {
System.out.println("Thread Name: " + Thread.currentThread().getName() + " write is over");
rrwl.writeLock().unlock();
System.out.println("Thread Name: " + Thread.currentThread().getName() + " write is release");
}
}
public static void main(String[] args) {
ReentrantReadWriteLock rrwl = new ReentrantReadWriteLock();
WritReadTest wrt = new WritReadTest(rrwl);
new Thread(new ReadTest(wrt)).start();
new Thread(new WriteTest(wrt)).start();
}
}
class ReadTest implements Runnable {
public WritReadTest wrt;
public ReadTest(WritReadTest wrt) {
this.wrt = wrt;
}
@Override
public void run() {
// wrt.read();
wrt.write();
}
}
class WriteTest implements Runnable {
private WritReadTest wrt;
public WriteTest(WritReadTest wrt) {
this.wrt = wrt;
}
@Override
public void run() {
wrt.write();
// wrt.read();
}
}
condition:條件。代替Object的監視方法(wait、notify、notifyAll)。直接通過代碼将線程放入一個等待隊列,然後等待其它線程喚醒。
class BoundedBuffer { final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final Object[] items = new Object[100];
int putptr, takeptr, count;
public void put(Object x) throws InterruptedException { lock.lock();
try {
while (count == items.length)
notFull.await();
items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count; notEmpty.signal();
} finally {
lock.unlock();
}
}
public Object take() throws InterruptedException { lock.lock();
try {
while (count == 0)
notEmpty.await();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count; notFull.signal();
return x; } finally {
lock.unlock();
}
}
}