实现思路:在多线程中,如果直接创建6个线程,分别进行对票数的修改,这样的并发操作是线程不安全的,这里不安全的原因是多个线程同时修改同一个变量。这里的票数是多个线程都能共享的数据,在线程1进行读取时,其他线程也会读取,在线程1进行对内存的修改,接着写回到内存时,其他线程获取到的票数就是不准确的。
可能说的不好理解,举一个例子:当窗口1发现还有一张票的时候,将票卖出去,还没来得及更新数据库中的票数时,窗口2这里显示的票数还是1,此时被另一个人买走,这时就出现了一张票被卖两次的情况。这种情况在现实生活如果发生的话是非常不好的,多线程就有这样的隐患。归根结底,原因在于多个线程同时修改了同一个变量。
解决方法->给修改票数方法加上一把锁,这里的锁是 synchronized,synchronized 会起到互斥效果, 某个线程执行到某个对象的 synchronized 中时, 其他线程如果也执行到同一个对象 synchronized 就会阻塞等待。
可以理解为,一个人上厕所的时候,会把门关上,不让别人进来,只有他出去了,别人在可能会进去。这里的synchronized就是保证了票数修改是线程安全的。
实现代码:
还有一些小细节没有写注释,因为我相信你一定可以看懂~比如获取当前系统时间、线程休眠、匿名内部类创建线程、try、catch捕获异常。
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Created with IntelliJ IDEA.
*
* @Author: 管坤坤
* @Date: 2021/12/08/19:59
* @Description:
*/
class Count{
Date date=new Date ();
SimpleDateFormat dateFormat=new SimpleDateFormat ("yyyy-MM-dd :hh:mm:ss");
static int count=600;
synchronized public void ticket(){
if(count>0){
System.out.println(Thread.currentThread().getName()+"票号"+count+" 出票时间: "+dateFormat.format (date));
count--;
}
}
}
public class threadDemo13 {
public static void main (String[] args) throws InterruptedException {
Count count=new Count ();
Thread t1=new Thread ("窗口1"){
@Override
public void run(){
while (true){
count.ticket ();
try {
Thread.sleep (100);
} catch (InterruptedException e) {
e.printStackTrace ();
}
}
}
};
Thread t2=new Thread ("窗口2"){
@Override
public void run(){
while (true){
count.ticket ();
try {
Thread.sleep (100);
} catch (InterruptedException e) {
e.printStackTrace ();
}
}
}
};
Thread t3=new Thread ("窗口3"){
@Override
public void run(){
while (true){
count.ticket ();
try {
Thread.sleep (100);
} catch (InterruptedException e) {
e.printStackTrace ();
}
}
}
};
Thread t4=new Thread ("窗口4"){
@Override
public void run(){
while (true){
count.ticket ();
try {
Thread.sleep (100);
} catch (InterruptedException e) {
e.printStackTrace ();
}
}
}
};
Thread t5=new Thread ("窗口5"){
@Override
public void run(){
while (true){
count.ticket ();
try {
Thread.sleep (100);
} catch (InterruptedException e) {
e.printStackTrace ();
}
}
}
};
Thread t6=new Thread ("窗口6"){
@Override
public void run(){
while (true){
count.ticket ();
try {
Thread.sleep (100);
} catch (InterruptedException e) {
e.printStackTrace ();
}
}
}
};
t1.start ();
t2.start ();
t3.start ();
t4.start ();
t5.start ();
t6.start ();
}
}