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();
}
}
}