学习到Lock对象啦,用它替换掉synchronized之前两个小例子。
效果差不多的,不过他有Condition特有的功能,这里没有体现出来。主要看替换点,结合前面synchronized写法,很好理解。
package com.cc.sellticket3;
import java.util.concurrent.locks.ReentrantLock;
/*
* 卖票服务
*/
public class TicketService {
private ReentrantLock lock = new ReentrantLock();
private int tickets = 50;
public TicketService() {
super();
}
public TicketService(int tickets) {
super();
this.tickets = tickets;
}
public void sellTickets() throws Exception {
try {
/*小测验-lock()方法比tryLock()快
if(lock.tryLock()) {
if(tickets > 0) {
tickets-- ;
System.out.println(Thread.currentThread().getName()+"窗口卖了1张票,待卖票数:"+tickets);
}else {
long time = System.currentTimeMillis() - TimeTools.getStartTime();
throw new Exception(Thread.currentThread().getName()+"窗口:卖完了! 耗时:" + time + "毫秒!" );
}
tryLock 耗时:14112毫秒
lock 耗时:6302毫秒!
}*/
lock.lock();
if(tickets > 0) {
tickets-- ;
System.out.println(Thread.currentThread().getName()+"窗口卖了1张票,待卖票数:"+tickets);
}else {
long time = System.currentTimeMillis() - TimeTools.getStartTime();
throw new Exception(Thread.currentThread().getName()+"窗口:卖完了! 耗时:" + time + "毫秒!" );
}
} catch (Exception e) {
throw new Exception(e.getMessage());
} finally {
if(lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
}
package com.cc.sellticket3;
/*
* 记录开始时间工具
*/
public class TimeTools {
private static long startTime = 0;
public static long getStartTime() {
return startTime;
}
public static void setStartTime(long startTime) {
TimeTools.startTime = startTime;
}
}
package com.cc.sellticket3;
/*
* 多开几个窗口卖票
*/
public class SellTicketThread extends Thread{
private TicketService service;
public SellTicketThread(TicketService service) {
super();
this.service = service;
}
@Override
public void run() {
while(true) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
service.sellTickets();
} catch (Exception e) {
System.err.println(e.getMessage());
break;
}
}
}
}
package com.cc.sellticket3;
/*
* 模拟卖票运行
*/
public class Run {
public static void main(String[] args) throws InterruptedException {
//今天卖票服务一共卖80张票--一般50张
TicketService service = new TicketService(80);
//开始卖票时间
TimeTools.setStartTime(System.currentTimeMillis());
//卖票一直到结束
SellTicketThread t1 = new SellTicketThread(service);
t1.setName("1号");
SellTicketThread t2 = new SellTicketThread(service);
t2.setName("2号");
SellTicketThread t3 = new SellTicketThread(service);
t3.setName("3号");
SellTicketThread t4 = new SellTicketThread(service);
t4.setName("4号");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
运行结果:
1号窗口卖了1张票,待卖票数:79
4号窗口卖了1张票,待卖票数:78
2号窗口卖了1张票,待卖票数:77
3号窗口卖了1张票,待卖票数:76
3号窗口卖了1张票,待卖票数:75
4号窗口卖了1张票,待卖票数:74
2号窗口卖了1张票,待卖票数:73
1号窗口卖了1张票,待卖票数:72
4号窗口卖了1张票,待卖票数:71
1号窗口卖了1张票,待卖票数:70
2号窗口卖了1张票,待卖票数:69
3号窗口卖了1张票,待卖票数:68
1号窗口卖了1张票,待卖票数:67
3号窗口卖了1张票,待卖票数:66
2号窗口卖了1张票,待卖票数:65
4号窗口卖了1张票,待卖票数:64
1号窗口卖了1张票,待卖票数:63
3号窗口卖了1张票,待卖票数:62
4号窗口卖了1张票,待卖票数:61
2号窗口卖了1张票,待卖票数:60
4号窗口卖了1张票,待卖票数:59
3号窗口卖了1张票,待卖票数:58
1号窗口卖了1张票,待卖票数:57
2号窗口卖了1张票,待卖票数:56
2号窗口卖了1张票,待卖票数:55
3号窗口卖了1张票,待卖票数:54
4号窗口卖了1张票,待卖票数:53
1号窗口卖了1张票,待卖票数:52
2号窗口卖了1张票,待卖票数:51
3号窗口卖了1张票,待卖票数:50
1号窗口卖了1张票,待卖票数:49
4号窗口卖了1张票,待卖票数:48
2号窗口卖了1张票,待卖票数:47
3号窗口卖了1张票,待卖票数:46
4号窗口卖了1张票,待卖票数:45
1号窗口卖了1张票,待卖票数:44
4号窗口卖了1张票,待卖票数:43
2号窗口卖了1张票,待卖票数:42
1号窗口卖了1张票,待卖票数:41
3号窗口卖了1张票,待卖票数:40
3号窗口卖了1张票,待卖票数:39
1号窗口卖了1张票,待卖票数:38
2号窗口卖了1张票,待卖票数:37
4号窗口卖了1张票,待卖票数:36
2号窗口卖了1张票,待卖票数:35
3号窗口卖了1张票,待卖票数:34
4号窗口卖了1张票,待卖票数:33
1号窗口卖了1张票,待卖票数:32
1号窗口卖了1张票,待卖票数:31
3号窗口卖了1张票,待卖票数:30
2号窗口卖了1张票,待卖票数:29
4号窗口卖了1张票,待卖票数:28
2号窗口卖了1张票,待卖票数:27
3号窗口卖了1张票,待卖票数:26
1号窗口卖了1张票,待卖票数:25
4号窗口卖了1张票,待卖票数:24
2号窗口卖了1张票,待卖票数:23
3号窗口卖了1张票,待卖票数:22
4号窗口卖了1张票,待卖票数:21
1号窗口卖了1张票,待卖票数:20
2号窗口卖了1张票,待卖票数:19
4号窗口卖了1张票,待卖票数:18
3号窗口卖了1张票,待卖票数:17
1号窗口卖了1张票,待卖票数:16
2号窗口卖了1张票,待卖票数:15
3号窗口卖了1张票,待卖票数:14
1号窗口卖了1张票,待卖票数:13
4号窗口卖了1张票,待卖票数:12
2号窗口卖了1张票,待卖票数:11
3号窗口卖了1张票,待卖票数:10
1号窗口卖了1张票,待卖票数:9
4号窗口卖了1张票,待卖票数:8
2号窗口卖了1张票,待卖票数:7
1号窗口卖了1张票,待卖票数:6
4号窗口卖了1张票,待卖票数:5
3号窗口卖了1张票,待卖票数:4
2号窗口卖了1张票,待卖票数:3
3号窗口卖了1张票,待卖票数:2
4号窗口卖了1张票,待卖票数:1
1号窗口卖了1张票,待卖票数:0
3号窗口:卖完了! 耗时:6302毫秒!
4号窗口:卖完了! 耗时:6302毫秒!
2号窗口:卖完了! 耗时:6302毫秒!
1号窗口:卖完了! 耗时:6302毫秒!
知识点:
ReentrantLock类的lock()和unlock()方法控制对象锁。