1、需要操作的共享对象,银行卡,大家都网购,用这张卡
package Thread_readWriteLock;
public class ShareAccount {
private String oid; //账号
private int cash; //账户余额
ShareAccount(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 +
'}';
}
}
2、刷卡的对象
package Thread_readWriteLock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author zhengchao
*/
public class User implements Runnable{
private String name; //用户名
private ShareAccount myCount; //所要操作的账户
private int iocash; //操作的金额,当然有正负之分了
private ReadWriteLock myLock; //执行操作所需的锁对象
private boolean isQuery; //是否查询
User(String name, ShareAccount myCount, int iocash, ReadWriteLock myLock, boolean isQuery) {
this.name = name;
this.myCount = myCount;
this.iocash = iocash;
this.myLock = myLock;
this.isQuery = isQuery;
}
//加Thread.sleep(1000);是为了让大家看运行结果,感受:可同时读
public void run() {
if (isQuery) {
//获取读锁
myLock.readLock().lock();
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(User.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("读:" + name + "正在查询" + myCount + "账户,当前金额为" + myCount.getCash());
//释放读锁
myLock.readLock().unlock();
} else {
//获取写锁
myLock.writeLock().lock();
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(User.class.getName()).log(Level.SEVERE, null, ex);
}
//执行现金业务
System.out.println("写:" + name + "正在操作" + myCount + "账户,金额为" + iocash +",当前金额为" + myCount.getCash());
myCount.setCash(myCount.getCash() + iocash);
System.out.println("写:" + name + "操作" + myCount + "账户成功,金额为" + iocash +",当前金额为" + myCount.getCash());
//释放写锁
myLock.writeLock().unlock();
}
}
}
3、测试案例
package Thread_readWriteLock;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
*
* @author zhengchao
*/
public class Test_ReadWriteLock {
public static void main(String[] args) throws InterruptedException{
ShareAccount account = new ShareAccount("95528",10000);
ReadWriteLock lock = new ReentrantReadWriteLock(false); //false:非公平性
//ExecutorService pool = Executors.newFixedThreadPool(2);
ThreadPoolExecutor pool = (ThreadPoolExecutor) Executors.newFixedThreadPool(2);
User boy = new User("郑超",account,0,lock,true);
User boy1 = new User("郑超1",account,0,lock,true);
User boy2 = new User("郑超2",account,0,lock,true);
User boy3 = new User("郑超3",account,0,lock,true);
User boy4 = new User("郑超4",account,0,lock,true);
User boy5 = new User("郑超5",account,0,lock,true);
User boy6 = new User("郑超6",account,0,lock,true);
User boy7 = new User("郑超7",account,0,lock,true);
User boy8 = new User("郑超8",account,0,lock,true);
User girl = new User("刘珍珍",account,-500,lock,false);
User girl1 = new User("刘珍珍1",account,-500,lock,false);
User girl2 = new User("刘珍珍2",account,-500,lock,false);
User girl3 = new User("刘珍珍3",account,-500,lock,false);
User girl4 = new User("刘珍珍4",account,-500,lock,false);
User girl5 = new User("刘珍珍5",account,-500,lock,false);
User girl6 = new User("刘珍珍6",account,-500,lock,false);
User girl7 = new User("刘珍珍7",account,-500,lock,false);
User girl8 = new User("刘珍珍8",account,-500,lock,false);
User girl9 = new User("刘珍珍9",account,-500,lock,false);
pool.execute(boy);
pool.execute(boy1);
pool.execute(boy2);
pool.execute(boy3);
pool.execute(boy4);
pool.execute(boy5);
pool.execute(boy6);
pool.execute(boy7);
pool.execute(boy8);
pool.execute(girl);
pool.execute(girl1);
pool.execute(girl2);
pool.execute(girl3);
pool.execute(girl4);
pool.execute(girl5);
pool.execute(girl6);
pool.execute(girl7);
pool.execute(girl8);
pool.execute(girl9);
/**
shutdown():执行后不再接收新任务,如果里面有任务,就执行完;
通常shutdown之后调用awaitTermination(long timeout, TimeUnit unit),
作用是:后者会阻塞当前线程,等待剩余任务执行完,然后继续往下执行。
shutdownNow():执行后不再接受新任务,如果有等待任务,移出队列;有正在执行的,尝试停止之;
*/
pool.shutdown();
pool.awaitTermination(30, TimeUnit.SECONDS); //停30s再执行后面的逻辑
System.out.println(account.getCash());
}
}
总结:
1、两个线程可同时读,读的时候无法写
2、只能一个线程写,写的时候不能多
有时候我们需要跟进某一个线程的执行,可以使用Future
package Thread_readWriteLock;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author zhengchao
*/
public class Test_ReadWriteLock {
public static void main(String[] args) throws InterruptedException, ExecutionException{
ShareAccount account = new ShareAccount("95528",10000);
ReadWriteLock lock = new ReentrantReadWriteLock(false); //false:非公平性
ReadWriteLock lock1 = new ReentrantReadWriteLock(true); //true:公平
//ExecutorService pool = Executors.newFixedThreadPool(2);
ThreadPoolExecutor pool = (ThreadPoolExecutor) Executors.newFixedThreadPool(2);
User girl0 = new User("刘珍珍0",account,-500,lock,false);
User girl1 = new User("刘珍珍1",account,-500,lock,false);
User girl2 = new User("刘珍珍2",account,-500,lock,false);
User girl3 = new User("刘珍珍3",account,-500,lock,false);
User girl4 = new User("刘珍珍4",account,-500,lock,false);
User girl5 = new User("刘珍珍5",account,-500,lock,false);
User girl6 = new User("刘珍珍6",account,-500,lock,false);
User girl7 = new User("刘珍珍7",account,-500,lock,false);
User girl8 = new User("刘珍珍8",account,-500,lock,false);
User girl9 = new User("刘珍珍9",account,-500,lock,false);
pool.execute(girl0);
pool.execute(girl1);
pool.execute(girl2);
pool.execute(girl3);
/**
* excute方法无返回值,submit方法有返回值
* Future接口提供方法来检测任务是否被执行完,等待任务执行完获得结果,
* 也可以设置任务执行的超时时间。这个设置超时的方法就是实现Java程序执行超时的关键。
*/
Future future = pool.submit(girl9);
future.get(); //girl9不执行完,下面的都不会执行
System.out.println("********");
Future future0 = pool.submit(girl8);
try {
future0.get(100, TimeUnit.MILLISECONDS); //设置超时时间:100ms
} catch (TimeoutException ex) {
System.out.println("********超时啦*****");
Logger.getLogger(Test_ReadWriteLock.class.getName()).log(Level.SEVERE, null, ex);
}
pool.execute(girl4);
pool.execute(girl5);
pool.execute(girl6);
pool.execute(girl7);
/**
shutdown():执行后不再接收新任务,如果里面有任务,就执行完;
通常shutdown之后调用awaitTermination(long timeout, TimeUnit unit),
作用是:后者会阻塞当前线程,等待剩余任务执行完,然后继续往下执行。
shutdownNow():执行后不再接受新任务,如果有等待任务,移出队列;有正在执行的,尝试停止之;
*/
pool.shutdown();
pool.awaitTermination(30, TimeUnit.SECONDS); //停30s再执行后面的逻辑
System.out.println(account.getCash());
}
}
运行结果:
run:
写:刘珍珍0正在操作MyCount{oid='95528', cash=10000}账户,金额为-500,当前金额为10000
写:刘珍珍0操作MyCount{oid='95528', cash=9500}账户成功,金额为-500,当前金额为9500
写:刘珍珍1正在操作MyCount{oid='95528', cash=9500}账户,金额为-500,当前金额为9500
写:刘珍珍1操作MyCount{oid='95528', cash=9000}账户成功,金额为-500,当前金额为9000
写:刘珍珍2正在操作MyCount{oid='95528', cash=9000}账户,金额为-500,当前金额为9000
写:刘珍珍2操作MyCount{oid='95528', cash=8500}账户成功,金额为-500,当前金额为8500
写:刘珍珍3正在操作MyCount{oid='95528', cash=8500}账户,金额为-500,当前金额为8500
写:刘珍珍3操作MyCount{oid='95528', cash=8000}账户成功,金额为-500,当前金额为8000
写:刘珍珍9正在操作MyCount{oid='95528', cash=8000}账户,金额为-500,当前金额为8000
写:刘珍珍9操作MyCount{oid='95528', cash=7500}账户成功,金额为-500,当前金额为7500
********
********超时啦*****
十一月 03, 2016 12:03:28 下午 Thread_readWriteLock.Test_ReadWriteLock main
严重: null
java.util.concurrent.TimeoutException
at java.util.concurrent.FutureTask.get(FutureTask.java:201)
at Thread_readWriteLock.Test_ReadWriteLock.main(Test_ReadWriteLock.java:56)
写:刘珍珍8正在操作MyCount{oid='95528', cash=7500}账户,金额为-500,当前金额为7500
写:刘珍珍8操作MyCount{oid='95528', cash=7000}账户成功,金额为-500,当前金额为7000
写:刘珍珍4正在操作MyCount{oid='95528', cash=7000}账户,金额为-500,当前金额为7000
写:刘珍珍4操作MyCount{oid='95528', cash=6500}账户成功,金额为-500,当前金额为6500
写:刘珍珍6正在操作MyCount{oid='95528', cash=6500}账户,金额为-500,当前金额为6500
写:刘珍珍6操作MyCount{oid='95528', cash=6000}账户成功,金额为-500,当前金额为6000
写:刘珍珍7正在操作MyCount{oid='95528', cash=6000}账户,金额为-500,当前金额为6000
写:刘珍珍7操作MyCount{oid='95528', cash=5500}账户成功,金额为-500,当前金额为5500
写:刘珍珍5正在操作MyCount{oid='95528', cash=5500}账户,金额为-500,当前金额为5500
写:刘珍珍5操作MyCount{oid='95528', cash=5000}账户成功,金额为-500,当前金额为5000
5000
成功构建 (总时间: 10 秒)