线程同步2.1卖票【应用】
-
案例需求
某电影院目前正在上映国产大片,共有100张票,而它有3个窗口卖票,请设计一个程序模拟该电影院卖票
-
实现步骤
-
定义一个类SellTicket实现Runnable接口,里面定义一个成员变量:private int tickets = 100;
-
在SellTicket类中重写run()方法实现卖票,代码步骤如下
-
判断票数大于0,就卖票,并告知是哪个窗口卖的
-
卖了票之后,总票数要减1
-
票没有了,也可能有人来问,所以这里用死循环让卖票的动作一直执行
-
定义一个测试类SellTicketDemo,里面有main方法,代码步骤如下
-
创建SellTicket类的对象
-
创建三个Thread类的对象,把SellTicket对象作为构造方法的参数,并给出对应的窗口名称
-
[Java] 纯文本查看 复制代码
3同步代码块解决数据安全问题【应用】01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public
class
SellTicket
implements
Runnable {
private
int
tickets =
100
;
//在SellTicket类中重写run()方法实现卖票,代码步骤如下
@Override
public
void
run() {
while
(
true
) {
if
(tickets >
0
) {
System.out.println(Thread.currentThread().getName() +
"正在出售第"
+ tickets +
"张票"
);
tickets--;
}
}
}
}
public
class
SellTicketDemo {
public
static
void
main(String[] args) {
//创建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();
}
}
-
安全问题出现的条件
-
是多线程环境
-
有共享数据
-
有多条语句操作共享数据
-
-
如何解决多线程安全问题呢?
-
基本思想:让程序没有安全问题的环境
-
-
怎么实现呢?
-
把多条语句操作共享数据的代码给锁起来,让任意时刻只能有一个线程执行即可
-
Java提供了同步代码块的方式来解决
-
-
同步代码块格式:
synchronized(任意对象) {
多条语句操作共享数据的代码
}synchronized(任意对象):就相当于给代码加锁了,任意对象就可以看成是一把锁
-
同步的好处和弊端
-
好处:解决了多线程的数据安全问题
-
弊端:当线程很多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率
-
-
[AppleScript] 纯文本查看 复制代码
5TCP通信程序练习【应用】01
02
03
04
05
06
07
08
09
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
代码演示public
class
SellTicket implements Runnable
{
private int tickets
=
100
;
private Object obj
=
new
Object
(
)
; @Override
public void
run
(
)
{
while
(
true
)
{
/
/
tickets
=
100
;
/
/
t
1
,
t
2
,
t
3
/
/
假设t
1
抢到了CPU的执行权
/
/
假设t
2
抢到了CPU的执行权
synchronized
(
obj
)
{
/
/
t
1
进来后,就会把这段代码给锁起来
if
(
tickets
>
0
)
{
try
{
Thread.sleep
(
100
)
;
/
/
t
1
休息
100
毫秒
}
catch
(
InterruptedException e
)
{
e.printStackTrace
(
)
;
}
/
/
窗口
1
正在出售第
100
张票
System.out.println
(
Thread.currentThread
(
)
.getName
(
)
+
"正在出售第"
+
tickets
+
"张票"
)
;
tickets
--; //tickets = 99;
}
}
/
/
t
1
出来了,这段代码的锁就被释放了
}
}
}
public
class
SellTicketDemo
{
public static void
main
(
String[] args
)
{
SellTicket st
=
new
SellTicket
(
)
; Thread t
1
=
new
Thread
(
st
,
"窗口1"
)
;
Thread t
2
=
new
Thread
(
st
,
"窗口2"
)
;
Thread t
3
=
new
Thread
(
st
,
"窗口3"
)
; t
1.
start
(
)
;
t
2.
start
(
)
;
t
3.
start
(
)
;
}
}
-
案例需求
客户端:数据来自于键盘录入,直到输入的数据是886,发送数据结束
服务端:接受到的数据写入文本文件中
-
案例分析
-
客户端创建对象,使用键盘录入循环接受数据,接受一行发送一行,直到键盘录入886为止
-
服务端创建对象,创建输出流对象指向文件,每接受一行数据后使用输出流输出到文件中,直到接受到null为止
-
-
代码实现
[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
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
ublic
class
ClientDemo
{
public static void
main
(
String[] args
)
throws IOException
{
/
/
创建客户端Socket对象
Socket s
=
new
Socket
(
"192.168.1.66"
,
10000
)
;
/
/
数据来自于键盘录入,直到输入的数据是
886
,发送数据结束
BufferedReader br
=
new
BufferedReader
(
new
InputStreamReader
(
System.
in
)
)
;
/
/
封装输出流对象
BufferedWriter bw
=
new
BufferedWriter
(
new
OutputStreamWriter
(
s.getOutputStream
(
)
)
)
;
String line;
while
(
(
line
=
br.readLine
(
)
)
!
=
null
)
{
if
(
"886"
.
equals
(
line
)
)
{
break;
}
bw.
write
(
line
)
;
bw.newLine
(
)
;
bw.flush
(
)
;
}
/
/
释放资源
s.
close
(
)
;
}
}
public
class
ServerDemo
{
public static void
main
(
String[] args
)
throws IOException
{
/
/
创建服务器Socket对象
ServerSocket ss
=
new
ServerSocket
(
10000
)
;
/
/
监听客户端连接,返回一个对应的Socket对象
Socket s
=
ss.accept
(
)
;
/
/
接收数据
BufferedReader br
=
new
BufferedReader
(
new
InputStreamReader
(
s.getInputStream
(
)
)
)
;
/
/
把数据写入文本文件
BufferedWriter bw
=
new
BufferedWriter
(
new
FileWriter
(
"myNet\\s.txt"
)
)
;
String line;
while
(
(
line
=
br.readLine
(
)
)
!
=
null
)
{
bw.
write
(
line
)
;
bw.newLine
(
)
;
bw.flush
(
)
;
}
/
/
释放资源
bw.
close
(
)
;
ss.
close
(
)
;
}
}
-
-
-