readWriteLock读写锁和Future

 
 

ReentrantReadWriteLock 和 ReentrantLock 不是继承关系,但都是基于 AbstractQueuedSynchronizer 来实现。

lock方法 是基于CAS 来实现的

注意: 在同一线程中,持有读锁后,不能直接调用写锁的lock方法 ,否则会造成死锁。

下面这个例子是在文例子的基础上,将普通锁改为读写锁,并添加账户余额查询的功能,代码如下
 
 

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class textBank {
	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 + '}';
	}
}


Future的使用,两个线程一块跑异步进行
public class TEXT {  
	public static void main(String[] args) throws InterruptedException, ExecutionException {
        long startTime = System.currentTimeMillis();
        // 第一步 网购厨具
        Callable<Chuju> onlineShopping = new Callable<Chuju>() {

            @Override
            public Chuju call() throws Exception {
                System.out.println("第一步:下单");
                System.out.println("第一步:等待送货");
                Thread.sleep(5000);  // 模拟送货时间
                System.out.println("第一步:快递送到");
                return new Chuju();
            }
            
        };
        FutureTask<Chuju> task = new FutureTask<Chuju>(onlineShopping);
        new Thread(task).start();
        // 第二步 去超市购买食材
        Thread.sleep(2000);  // 模拟购买食材时间
        Shicai shicai = new Shicai();
        System.out.println("第二步:食材到位");
        // 第三步 用厨具烹饪食材
        if (!task.isDone()) {  // 联系快递员,询问是否到货
            System.out.println("第三步:厨具还没到,心情好就等着(心情不好就调用cancel方法取消订单)");
        }
        Chuju chuju = task.get();
        System.out.println("第三步:厨具到位,开始展现厨艺");
        cook(chuju, shicai);
        
        System.out.println("总共用时" + (System.currentTimeMillis() - startTime) + "ms");
    }
    
    //  用厨具烹饪食材
    static void cook(Chuju chuju, Shicai shicai) {}
    
    // 厨具类
    static class Chuju {}
    
    // 食材类
    static class Shicai {}
}

在快递厨具没来时,可以先买菜,在问问快递小哥快递来了吗?如果没来,等会,不想等了就调用cancel方法取消订单


这是API对FutureTask的解释



猜你喜欢

转载自blog.csdn.net/songaodi/article/details/80720365