java多线程详解(三)-----线程的同步

今天参照大牛的博客,自己写了一下多线程实现窗口卖票的程序,很久没写多线程了,记得第一家公司就是做的这个,今天记录一下,重写一下。

利用多线程模拟 3 个窗口卖票

继承 Thread 类

package Thread;

public class SellThread extends Thread {
        //定义一共有 50 张票,注意声明为 static,表示几个窗口共享
    private static int num = 50;

    //调用父类构造方法,给线程命名
    public SellThread(String string) {
        super(string);
    }

    @Override
    public void run() {
        for (int i = 0; i < 50; i++) {
            synchronized (this.getClass()) {
                if (num > 0) {
                    try {
                        sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(this.currentThread().getName() + "卖出一张票,剩余" + (--num) + "张");
                }
            }
        }
    }
}

实现runnable接口:

package Thread;

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

public class SellRunnable implements Runnable {
    //定义一共有 50 张票,继承机制开启线程,资源是共享的,所以不用加 static
    private int num = 50;
    //    @Override
//    public void run() {
//        //票分 50 次卖完
//        for(int i = 0 ; i < 50 ;i ++){
//            sell();
//        }
//    }
//
//    private synchronized void sell(){
//        if(num > 0){
//            try {
//                //模拟卖一次票所需时间
//                Thread.sleep(10);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            System.out.println(Thread.currentThread().getName()+"卖出一张票,剩余"+(--num)+"张");
//        }
//    }
    //创建一个锁对象
    Lock l = new ReentrantLock();

    @Override
    public void run() {
        //票分 50 次卖完
        for (int i = 0; i < 50; i++) {
            //获取锁
            l.lock();
            try {
                if (num > 0) {
                    //模拟卖一次票所需时间
                    Thread.sleep(1000);
                    System.out.println(Thread.currentThread().getName() + "卖出一张票,剩余" + (--num) + "张");
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //释放锁
                l.unlock();
            }
        }
    }
}

main函数

package Thread;

public class Main {
    public static void main(String[] args) {
//        SellThread sellThread1 = new SellThread("A窗口");
//        SellThread sellThread2 = new SellThread("B窗口");
//        SellThread sellThread3 = new SellThread("C窗口");
//        sellThread1.start();
//        sellThread2.start();
//        sellThread3.start();
        SellRunnable r = new SellRunnable();
        Thread t1 = new Thread(r,"A窗口");
        Thread t2 = new Thread(r,"B窗口");
        Thread t3 = new Thread(r,"C窗口");
        t1.start();
        t2.start();
        t3.start();
    }
}

这里用了三种方法做线程同步:
1,使用同步代码块
2,使用同步方法
3,使用锁机制

为什么要使用线程同步,如果不使用线程同步,可能两个线程会同时进入代码块,导致窗口间卖了同一张票,不能使票保持独占。
在这里插入图片描述
其中第一个继承thread线程的方式用了同步代码块,第二种实现runnable接口用了同步方法和锁机制,当然实现runnable接口也可以使用同步代码块。但是继承thread使用同步方法和锁机制时会出现问题,因为new了三个对象,他们的三个对象的sell方法和lock对象不同,到最后会出现负票情况。

参考地址:https://www.cnblogs.com/ysocean/p/6883729.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值