显示锁
- lock 接口和Synchronized比较
Synchronized代码简洁,
lock :获取锁可以被中断,超时获取锁,尝试的获取锁 - lock接口和核心方法
lock():
unlock()
trylock()/** * 使用显示锁的范式 */ public class LockDome { private Lock lock = new ReentrantLock(); private int count; public void increament() { lock.lock(); try { count++; } finally { lock.unlock(); } } }
- 可重入锁ReentrantLock、所谓的公平和非公平
可重入:获取锁的多次,锁重入一次,锁的数量+1 ,执行完这个方法执行-1 方法执行完毕为0
公平锁:如果在时间上先对锁进行获取的请求一定先被满足public synchronized void test1() { count++; test1(); } public synchronized void test2() { count++; test1(); }
非公平锁:如果在时间上先对锁进行获取的请求不先被满足
非公平锁的效率一般比公平锁更高
ReentrantLock 和syn都是排它锁,只允许一个线程访问, - ReadWriteLock接口和读写锁ReetrantReadWriteLock
读写锁:同一时刻,允许多个读线程同时访问,但是写线程访问的时候,所有的读和写都会阻塞
读多,写少的情况下,可以使用读写锁
用法 :
商品类:
public class GoodsInfo {
private String name;
private int totalMoney;
private int storeNumber;
public GoodsInfo(String name, int totalMoney, int storeNumber) {
this.name = name;
this.totalMoney = totalMoney;
this.storeNumber = storeNumber;
}
public int getTotalMoney() {
return totalMoney;
}
public int getStoreNumber() {
return storeNumber;
}
public void changNubmer(int sellNumber){
this.totalMoney += sellNumber*26;
this.storeNumber -= sellNumber;
}
}
业务类:
/**
* 使用读写锁操作
*/
public class UseRwLock implements GoodsService {
private GoodsInfo goodsInfo;
//缺省 非公平锁
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final Lock getlock = lock.readLock();//读锁
private final Lock writelock = lock.writeLock();//写锁
public UseRwLock(GoodsInfo goodsInfo) {
this.goodsInfo = goodsInfo;
}
@Override
public GoodsInfo getNum() {
getlock.lock();
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
getlock.unlock();
}
return this.goodsInfo;
}
@Override
public void setNum(int number) {
getlock.lock();
try {
Thread.sleep(5);
goodsInfo.changNubmer(number);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
getlock.unlock();
}
}
}
启动类:
public class BusiApp {
static final int readWriteratio = 10;//读写线程的比例
static final int minthreadcount = 3;//最少线程
private static class GetThread implements Runnable {
GoodsService goodsService;
public GetThread(GoodsService goodsService) {
this.goodsService = goodsService;
}
@Override
public void run() {
long start = System.currentTimeMillis();
for (int i = 0; i < 100; i++) {
goodsService.getNum();
}
System.out.println(Thread.currentThread().getName()+" 读取商品耗时 。。。。。: " + (System.currentTimeMillis() - start));
}
} private static class SetThread implements Runnable {
GoodsService goodsService;
public SetThread(GoodsService goodsService) {
this.goodsService = goodsService;
}
@Override
public void run() {
long start = System.currentTimeMillis();
Random r = new Random();
for (int i = 0; i < 10; i++) {
goodsService.setNum(r.nextInt(10));
}
System.out.println(Thread.currentThread().getName()+" 写商品耗时 。。。。。: " + (System.currentTimeMillis() - start));
}
}
public static void main(String[] args) throws InterruptedException {
GoodsInfo goodsInfo = new GoodsInfo("CPU",10000,10000);
GoodsService goodsService = new UseSyn(goodsInfo);
for (int i = 0; i < minthreadcount; i++) {
Thread set = new Thread(new SetThread(goodsService));
for (int j = 0; j < readWriteratio; j++) {
Thread get = new Thread(new GetThread(goodsService));
get.start();
}
Thread.sleep(100);
set.start();
}
}
}
相比Syn效率提升非常明显
5. Condition 和lock实现等待通知
public class ExpressCond {
public final static String CITY = "Shanghai";
private int km; // 快递运输里程数
private String site; // 快递到达地点
private Lock kmlock = new ReentrantLock();
private Lock sitelock = new ReentrantLock();
private Condition kmcond = kmlock.newCondition();
private Condition sitecond = sitelock.newCondition();
public ExpressCond() {
}
public ExpressCond(int km, String site) {
this.km = km;
this.site = site;
}
// 变化公里数 然后通知处于wait状态并需要处理公里数的线程进行业务处理
public void changKm() {
kmlock.lock();
try {
this.km = 101;
kmcond.signal();
} finally {
kmlock.unlock();
}
}
// 变化地点 然后通知处于wait状态并需要处理地点的线程进行业务处理
public void changeSite() {
sitelock.lock();
try {
this.site = "北京";
sitecond.signal();
} finally {
sitelock.unlock();
}
}
public void waitKm() {
kmlock.lock();
try {
while (this.km <= 100) {
try {
kmcond.await();
System.out.println("我是里程 当前线程" + Thread.currentThread().getName() + " is be notify");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} finally {
kmlock.unlock();
}
}
public void waitSite() {
sitelock.lock();
try {
while (CITY.equals(this.site)) {
try {
sitecond.await();
System.out.println("我是地址 当前线程" + Thread.currentThread().getName() + " is be notify");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("我是地址 " + Thread.currentThread().getName() + " 货已经送到 site = " + this.site);
} finally {
sitelock.unlock();
}
}
}
- 了解LockSupper
作用: 1. 阻塞一个线程
2. 唤醒一个线程
3. 构建同步组件的基础工具
park开头的方法 进行阻塞
unpark 方法 唤醒