Java多线程-新特征-锁(下)-学习笔记4_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > Java多线程-新特征-锁(下)-学习笔记4

Java多线程-新特征-锁(下)-学习笔记4

 2014/5/22 1:09:41  wang吖  程序员俱乐部  我要评论(0)
  • 摘要:在上文中提到了Lock接口以及对象,使用它,很优雅的控制了竞争资源的安全访问,但是这种锁不区分读写,称这种锁为普通锁。为了提高性能,Java提供了读写锁,在读的地方使用读锁,在写的地方使用写锁,灵活控制,在一定程度上提高了程序的执行效率。Java中读写锁有个接口java.util.concurrent.locks.ReadWriteLock,也有具体的实现ReentrantReadWriteLock,详细的API可以查看JavaAPI文档。下面这个例子是在文例子的基础上,将普通锁改为读写锁
  • 标签:笔记 学习 多线程 Java 学习笔记 线程

在上文中提到了Lock接口以及对象,使用它,很优雅的控制了竞争资源的安全访问,但是这种锁不区分读写,称这种锁为普通锁。为了提高性能,Java提供了读写锁,在读的地方使用读锁,在写的地方使用写锁,灵活控制,在一定程度上提高了程序的执行效率。

Java中读写锁有个接口java.util.concurrent.locks.ReadWriteLock,也有具体的实现ReentrantReadWriteLock,详细的API可以查看JavaAPI文档。

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

class="java">import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

//线程锁对象
public class WriteReadLockTest {

	public static void main(String[] args) {
		WriteReadLockTest wrt = new WriteReadLockTest();

		// 创建并发访问的账户 来个一个亿过把有钱人的瘾
		MyAccount myAcc = wrt.new MyAccount("95599200901215522", 100000000);

		// 创建一个对象锁
		ReentrantReadWriteLock lock = new ReentrantReadWriteLock(false);

		// 创建一个线程池
		ExecutorService pl = Executors.newFixedThreadPool(2);

		// 创建并发用户 一张信用卡,存的存,取的取,好热闹啊
		User u1 = wrt.new User("王五", myAcc, 100000, lock, false);
		User u2 = wrt.new User("王五他爹", myAcc, 0, lock, true);
		User u3 = wrt.new User("王五他弟", myAcc, -400000, lock, false);
		User u4 = wrt.new User("王五他妹", myAcc, 100000, lock, false);
		User u5 = wrt.new User("王五", myAcc, 0, lock, true);// 查询
		User u6 = wrt.new User("王五", myAcc, 100000, lock, false);

		pl.execute(u1);
		pl.execute(u2);
		pl.execute(u3);
		pl.execute(u4);
		pl.execute(u5);
		pl.execute(u6);

		pl.shutdown();
	}

	class User implements Runnable {

		private String name;
		private MyAccount myAccount;
		private int opcash;// 操作金额
		private ReadWriteLock myLock;// 锁对象
		private boolean isCheck;// 是否查询

		public User(String name, MyAccount myAccount, int opcash,
				ReadWriteLock myLock, boolean isCheck) {
			this.name = name;
			this.myAccount = myAccount;
			this.opcash = opcash;
			this.myLock = myLock;
			this.isCheck = isCheck;
		}

		@Override
		public void run() {
			String op;
			if (opcash > 0) {
				op = "存款";
			} else if (opcash < 0) {
				op = "取款";
			} else {
				op = "查询";
			}

			if (isCheck) {
				// 获取读锁
				myLock.readLock().lock();
				System.err.println("读:" + name + "正在操作" + myAccount + "账户,"
						+ op + "当前金额为" + myAccount.getCash());
				// 释放读锁
				myLock.readLock().unlock();
			} else {
				// 获取写锁
				myLock.writeLock().lock();
				// 执行现金业务
				System.out.println("写:" + name + "正在操作" + myAccount + "账户,"
						+ op + "金额为" + opcash + ",当前金额为" + myAccount.getCash());
				myAccount.setCash(myAccount.getCash() + opcash);
				System.out.println("写:" + name + "操作" + myAccount + "账户成功,"
						+ op + "金额为" + opcash + ",当前金额为" + myAccount.getCash());

				// 释放写锁,否则别的线程没有机会执行了
				myLock.writeLock().unlock();
			}

		}

	}

	// 信用卡,可随意透支
	class MyAccount {
		private String cardno;// 卡号
		private int cash;// 余额 测试就直接用int了

		public MyAccount(String cardno, int cash) {
			super();
			this.cardno = cardno;
			this.cash = cash;
		}

		public String getCardno() {
			return cardno;
		}

		public void setCardno(String cardno) {
			this.cardno = cardno;
		}

		public int getCash() {
			return cash;
		}

		public void setCash(int cash) {
			this.cash = cash;
		}

		@Override
		public String toString() {
			return "MyAccount{" + "卡号='" + cardno + '\'' + ", 余额=" + cash + '}';
		}
	}
}

?

运行结果:

写:王五正在操作MyAccount{卡号='95599200901215522', 余额=100000000}账户,存款金额为100000,当前金额为100000000
写:王五操作MyAccount{卡号='95599200901215522', 余额=100100000}账户成功,存款金额为100000,当前金额为100100000
读:王五他爹正在操作MyAccount{卡号='95599200901215522', 余额=100100000}账户,查询当前金额为100100000
写:王五他妹正在操作MyAccount{卡号='95599200901215522', 余额=100100000}账户,存款金额为100000,当前金额为100100000
写:王五他妹操作MyAccount{卡号='95599200901215522', 余额=100200000}账户成功,存款金额为100000,当前金额为100200000
写:王五他弟正在操作MyAccount{卡号='95599200901215522', 余额=100200000}账户,取款金额为-400000,当前金额为100200000
写:王五他弟操作MyAccount{卡号='95599200901215522', 余额=99800000}账户成功,取款金额为-400000,当前金额为99800000
写:王五正在操作MyAccount{卡号='95599200901215522', 余额=99800000}账户,存款金额为100000,当前金额为99800000
写:王五操作MyAccount{卡号='95599200901215522', 余额=99900000}账户成功,存款金额为100000,当前金额为99900000
读:王五正在操作MyAccount{卡号='95599200901215522', 余额=99900000}账户,查询当前金额为99900000

?

上一篇: 三重大山-重载 重写 重绘 下一篇: 没有下一篇了!
发表评论
用户名: 匿名