Java-多线程实现卖票

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
SellTicketDemo:

package com.fluffysponge;

/*
* 需求:
* 某电影院目前正在上映国产大片,共有100张票,而它有3个窗口卖票,请设计一个程序模拟该电影院卖票
* 思路:
* 1.定义一个类SellTicket实现Runnable接口,里面定义一个成员变量:private int tickets = 100;
* 2.在SellTicket类中重写run()方法实现卖票,代码步骤如下
* A:判断票数大于0,就卖票,并告知是哪个窗口卖的
* B:卖了票之后,总票数要减1
* C:票没有了,也有可能有人来问,所以这里用死循环让卖票的动作一直执行
* 3.定义一个测试类SellTicketDemo,里面有main方法,代码步骤如下:
* A.创建SellTicket类对象
* B.创建三个Thread类的对象,把SellTicket对象作为构造方法的参数,并给出对应的窗口名称
* C.启动线程
* */
public class SellTicketDemo {
public static void main(String[] args) {
// A.创建SellTicket类对象
// B.创建三个Thread类的对象,把SellTicket对象作为构造方法Thread t1 = new Thread(st,"窗口1");的参数,并给出对应的窗口名称
// C.启动线程

//创建SellTicket类对象
SellTicket st = new SellTicket();

//创建三个Thread类的对象,把SellTicket对象作为构造方法的参数,并给出对应的窗口名称
Thread t1 = new Thread(st, "窗口1");
Thread t2 = new Thread(st, "窗口2");
Thread t3 = new Thread(st, "窗口3");

//启动线程
t1.start();
t2.start();
t3.start();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
SellTicket:

package com.fluffysponge;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

//定义一个类SellTicket实现Runnable接口,里面定义一个成员变量:private int tickets = 100;
public class SellTicket implements Runnable {
private static int tickets = 100;
//private Object obj = new Object();
//private int x = 0;

/*
* Lock中提供了获得锁和释放锁的方法
* void lock():获得锁
* void unlock():释放锁
*
* Lock是接口不能直接实例化,这里采用它的实现类ReentrantLock来实例化
* ReentrantLock():创建一个ReentrantLock的实例
* */
private Lock lock = new ReentrantLock();

@Override
public void run() {
while (true) {
try{
lock.lock();
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "");
tickets --;
}
}finally {//防止上面语句出现错误导致锁未释放,所以释放锁的操作放在finally里确保总是可以执行。
lock.unlock();
}

}
}

//在SellTicket类中重写run()方法实现卖票,代码步骤如下
// @Override
// public void run() {
// //A:判断票数大于0,就卖票,并告知是哪个窗口卖的
// //B:卖了票之后,总票数要减1
// //C:票没有了,也有可能有人来问,所以这里用死循环让卖票的动作一直执行
// while (true) {
// if (x % 2 == 0) {
//// synchronized (obj) {
//// synchronized (this) {
// synchronized (SellTicket.class) {
// if (tickets > 0) {
// try {
// //通过sleep()方法模拟出票时间
// Thread.sleep(100);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
// tickets--;
// }
// }
// } else {
//// synchronized (obj) {
//// if (tickets > 0) {
//// try {
//// //通过sleep()方法模拟出票时间
//// Thread.sleep(100);
//// } catch (InterruptedException e) {
//// e.printStackTrace();
//// }
//// System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
//// tickets--;
//// }
//// }
// sellTicket();
// }
// x++;
// }
// }

// private void sellTicket() {
// synchronized (obj) {
// if (tickets > 0) {
// try {
// //通过sleep()方法模拟出票时间
// Thread.sleep(100);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
// tickets--;
// }
// }
// }

// private synchronized void sellTicket() {
// if (tickets > 0) {
// try {
// //通过sleep()方法模拟出票时间
// Thread.sleep(100);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
// tickets--;
// }
// }

// private static synchronized void sellTicket() {
// if (tickets > 0) {
// try {
// //通过sleep()方法模拟出票时间
// Thread.sleep(100);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
// tickets--;
// }
// }

}