Java5 的 java.util.concurrent.locks 为锁 和 等待条件 提供一个框架的接口 和 类,它不同于内置同步和监视器。更灵活地使用锁和条件。
java.util.concurrent.locks包的接口:
|-- Lock接口--------替代了synchronized
方法和语句的使用。为 同步代码块 和 同步函数 提供了更广泛的 锁定 操作,将同步的隐示锁操作变成实现操作、
|-- ReentrantLock类--------一个可重入的互斥锁Lock
,它封装了隐示锁操作的方法,但功能更强大。(一个实现了Lock接口的类)
|-- lock()--------获取锁、
|-- unlock()------释放锁、
|-- Condition接口------替代了 Object 监视器方法的使用。对Object的监视器方法(wait
、notify
和notifyAll
)进行单独封装,变成监视器对象,可以和任意Lock
实现组合使用。
|-- await()------等待。throws InterruptedException、
|-- signal()-----唤醒一个等待线程。
|-- signalAll()---唤醒所有等待线程。
/*
北京烤鸭制作和消费的实现
至少要有两个线程:
1.生产烤鸭的线程
生产线程的任务,生产烤鸭。
2.消费烤鸭的线程
消费线程的任务,消费烤鸭。
1线程和2线程是两个不同对象,有两种不同的run方法,但是他们都是在操作同一资源。
都是对共享资源烤鸭的操作,为了避免出现线程安全问题,我们要使用同步。
可以把共享资源和对共享资源的操作方法封装在缓冲区。
代码实现:
1.创建一个缓冲区,
2.创建两个线程任务,
3.创建线程,
4.开启线程。
*/
//简单烤鸭,生产一只,消费一只
//引入包。。。
import java.util.concurrent.locks.*;
class KaoYaTest
{
public static void main(String[] args)
{
//创建共享资源对象
KaoYaBuffer kaoya = new KaoYaBuffer();
//创建生产任务
ShengChang sc = new ShengChang(kaoya);
//创建消费任务
XiaoFei xf = new XiaoFei(kaoya);
Thread t1 = new Thread(sc,"张三");//张三线程
Thread t2 = new Thread(sc,"李四");
Thread t3 = new Thread(xf,"王五");
Thread t4 = new Thread(xf,"赵六");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
//缓冲区
class KaoYaBuffer
{
//创建一个互斥锁
final Lock lock = new ReentrantLock();
//创建生产监视器
final Condition shengchang_condi = lock.newCondition();
//创建消费监视器
final Condition xiaofei_condi = lock.newCondition();
//烤鸭的名字
private String name;
//烤鸭的编号
private int count = 1;
//标记
private boolean flag = false;
//对烤鸭的生产操作
public void set(String str){
//获取锁
lock.lock();
try{
while(flag)
//当有烤鸭时,生产等待
try{shengchang_condi.await();}catch(InterruptedException e){}
name = str + count;
count++;
System.out.println(Thread.currentThread().getName()+"生产"+name);
flag = true;//把标记改成有烤鸭状态
//唤醒消费线程
xiaofei_condi.signal();
}finally{
//释放锁
lock.unlock();
}
}
//对烤鸭的消费操作
public void get(){
lock.lock();
try{
while(!flag)
try{xiaofei_condi.await();}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+"消费"+name);
flag = false;
shengchang_condi.signal();
}finally{
lock.unlock();
}
}
}
//生产线程任务
class ShengChang implements Runnable
{
private KaoYaBuffer k;
ShengChang(KaoYaBuffer k){
this.k = k;
}
public void run(){
while(true){k.set("北京烤鸭");}
}
}
//消费线程任务
class XiaoFei implements Runnable
{
private KaoYaBuffer k;
XiaoFei(KaoYaBuffer k){
this.k = k;
}
public void run(){
while(true){k.get();}
}
}
/** 存钱取钱操作 **/
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* Java线程:锁
*
* @author leizhimin 2009-11-5 10:57:29
*/
public class Test {
public static void main(String[] args) {
//创建并发访问的账户
MyCount myCount = new MyCount("95599200901215522", 10000);
//创建一个锁对象
ReadWriteLock lock = new ReentrantReadWriteLock(false);
//创建一个线程池
ExecutorService pool = Executors.newFixedThreadPool(2);
//创建一些并发访问用户,一个信用卡,存的存,取的取,好热闹啊
User u1 = new User("张三", myCount, -4000, lock, false);
User u2 = new User("张三他爹", myCount, 6000, lock, false);
User u3 = new User("张三他弟", myCount, -8000, lock, false);
User u4 = new User("张三", myCount, 800, lock, false);
User u5 = new User("张三他爹", myCount, 0, lock, true);
//在线程池中执行各个用户的操作
pool.execute(u1);
pool.execute(u2);
pool.execute(u3);
pool.execute(u4);
pool.execute(u5);
//关闭线程池
pool.shutdown();
}
}
/**
* 信用卡的用户
*/
class User implements Runnable {
private String name; //用户名
private MyCount myCount; //所要操作的账户
private int iocash; //操作的金额,当然有正负之分了
private ReadWriteLock myLock; //执行操作所需的锁对象
private boolean ischeck; //是否查询
User(String name, MyCount myCount, int iocash, ReadWriteLock myLock, boolean ischeck) {
this.name = name;
this.myCount = myCount;
this.iocash = iocash;
this.myLock = myLock;
this.ischeck = ischeck;
}
public void run() {
if (ischeck) {
//获取读锁
myLock.readLock().lock();
System.out.println("读:" + name + "正在查询" + myCount + "账户,当前金额为" + myCount.getCash());
//释放读锁
myLock.readLock().unlock();
} else {
//获取写锁
myLock.writeLock().lock();
//执行现金业务
System.out.println("写:" + name + "正在操作" + myCount + "账户,金额为" + iocash + ",当前金额为" + myCount.getCash());
myCount.setCash(myCount.getCash() + iocash);
System.out.println("写:" + name + "操作" + myCount + "账户成功,金额为" + iocash + ",当前金额为" + myCount.getCash());
//释放写锁
myLock.writeLock().unlock();
}
}
}
/**
* 信用卡账户,可随意透支
*/
class MyCount {
private String oid; //账号
private int cash; //账户余额
MyCount(String oid, int cash) {
this.oid = oid;
this.cash = cash;
}
public String getOid() {
return oid;
}
public void setOid(String oid) {
this.oid = oid;
}
public int getCash() {
return cash;
}
public void setCash(int cash) {
this.cash = cash;
}
@Override
public String toString() {
return "MyCount{" +
"oid='" + oid + '\'' +
", cash=" + cash +
'}';
}
}