售票案例
线程状态
售票的动作需要被多个线程同时执行,所以要使用多线程技术
代码示例-线程不安全
代码
class Ticket implements Runnable{
private int tickets = 20;
/*售票动作需要被多线程执行,那就是线程任务代码*/
private Object object = new Object();
public void run() {
while (true)
{
if (tickets > 0)
{
try {
tickets--;
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() +"..........."+ tickets);
}
if (tickets<=0)
{
return;
}
}
}
}
public class ThreadDemo {
public static void main(String[] args) {
/*创建runnable接口的子类对象*/
Ticket ticket = new Ticket();
/*创建4个线程对象*/
Thread t1 = new Thread(ticket);
Thread t2 = new Thread(ticket);
Thread t3 = new Thread(ticket);
Thread t4 = new Thread(ticket);
/*开启线程*/
t1.start();
t2.start();
t3.start();
t4.start();
}
}
执行结果
Thread-1...........16
Thread-2...........16
Thread-3...........16
Thread-0...........16
Thread-3...........12
Thread-2...........12
Thread-1...........12
Thread-0...........9
Thread-0...........8
Thread-3...........8
Thread-2...........8
Thread-1...........8
Thread-1...........4
Thread-0...........4
Thread-3...........4
Thread-2...........4
Thread-2...........0
Thread-3...........0
Thread-1...........0
Thread-0...........0
运行结果分析
横向箭头代表CPU切换,竖向箭头代表程序向下执行.
可以看到当判断完票数是否>0后且在执行票数–前发生CPU执行线程的切换(线程进入临时阻塞状态)
代码示例-线程安全
class Ticket implements Runnable{
private int tickets = 20;
/*售票动作需要被多线程执行,那就是线程任务代码*/
private Object object = new Object();
public void run() {
while (true)
{
/**
* obj相当于锁
* 火车上的卫生间,有一个显示牌表示有没有人在用,
* 如果有人等待,如果无人进去锁门。
*/
synchronized (object)
{
if (tickets > 0)
{
try {
tickets--;
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() +"..........."+ tickets);
}
}
if (tickets<=0)
{
return;
}
}
}
}
public class ThreadDemo {
public static void main(String[] args) {
/*创建runnable接口的子类对象*/
Ticket ticket = new Ticket();
/*创建4个线程对象*/
Thread t1 = new Thread(ticket);
Thread t2 = new Thread(ticket);
Thread t3 = new Thread(ticket);
Thread t4 = new Thread(ticket);
/*开启线程*/
t1.start();
t2.start();
t3.start();
t4.start();
}
}
执行结果
Thread-1...........19
Thread-1...........18
Thread-1...........17
Thread-1...........16
Thread-1...........15
Thread-1...........14
Thread-1...........13
Thread-1...........12
Thread-1...........11
Thread-1...........10
Thread-1...........9
Thread-1...........8
Thread-1...........7
Thread-1...........6
Thread-1...........5
Thread-1...........4
Thread-1...........3
Thread-1...........2
Thread-1...........1
Thread-1...........0
线程问题发生的原因
- 1.多个线程在操作共享的数据
- 2.线程任务操作共享数据的代码有多条运算
解决方法
- 只要让一个线程在执行线程任务时,将多条操作共享数据的代码执行完,在执行过程中,不要让其他线程参与运算。
Java实现同步的方法
- Java中解决此问题是通过代码块来完成的。
- 这个代码块称为同步代码块syschronized
- syschronized(){}
同步的前提
- 必须保证多个线程在同步中使用同一个锁
- synchronized (new Object())是错误的
同步的好处
- 解决了多线程的安全性问题
同步的弊端
- 降低的程序的性能
如何区分同步
- 同步通过锁来判断是否为同一个同步