用线程同步技术实现一个模拟的列车售票系统,用六个窗口出售500张车票.打印处每个售票窗口的出票号码和出票时间。

实现思路:在多线程中,如果直接创建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 ();
    }
}

思考:run()、和start()两种方法,创建线程有什么不同?

猜你喜欢

转载自blog.csdn.net/guankunkunwd/article/details/121800637