PS.名字什么的不重要,改成了糖果,效果是一样的。
不考虑顺序的卖票线程程序,线程不安全模式
将票改成了糖果:

public class CandyDemo {
    public static void main(String[] args) throws IOException {
        //读取配置文件:.properties
        Properties p = new Properties();
        //使用配置文件,可以随时修改配置文件从而改变数据传输
        //路径中没有盘符,则默认在项目的目录下,在项目默认路径中添加文件,
        //文件内容为    count=100
        p.load(new FileReader("count.properties"));
        //获取票数
        String count = p.getProperty("count");
        //将糖的数量定下来,创建代表糖的类
        CandyNumber c = new CandyNumber();
        //添加100颗糖
        c.setCount(Integer.parseInt(count));
        //创建对象,代表四个小朋友
        //同时让四个小朋友看到共享的一百颗糖
        Candys c1 = new Candys(c);
        Candys c2 = new Candys(c);
        Candys c3 = new Candys(c);
        Candys c4 = new Candys(c);
        //创建四个线程,代表小朋友的行为
        //使用直接创建名字的构造方法,Thread类中,可以直接指定名字构造
        Thread t1 = new Thread(c1, "小明");
        Thread t2 = new Thread(c2, "小刚");
        Thread t3 = new Thread(c3, "小华");
        Thread t4 = new Thread(c4, "小萌");
        //开启线程,活动开始
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

class Candys implements Runnable {
    //由于糖果总共只有一百颗,所以需要将总数定义为公共使用数据,让所有人公用这个数据
    //但是由于要共享数据,又要频繁改值,并且线程执行没有顺序,
    // 所以static,会限定类的使用次数,每一次新建的类,调用的线程,都会使用static的数值,影响灵活性。
    //static int candy=100;      //无法优质的解决抢糖的顺序问题,所以放弃这个
    //所以引入一个引用类型,来保证少糖的顺序
    //注入CandyNumberd的类来当做属性,实现静态共享
    CandyNumber candy;

    //使用有参构造,来完成属性的赋值
    //只要给定的参数一样,则能保证每个线程创建的对象中的CandyNumber属性是一样的
    //由于类的对象是传地址,所以当传入参数相同的时候,就能保证他们使用的都是同一个candy
    public Candys(CandyNumber cnady) {
        this.candy = cnady;
    }
    @Override
    public void run() {
        //如果糖没有抢完,就继续活动
        boolean isCandy=true;
        while (isCandy) {
            //使用同步代码块锁,锁住核心代码块,在一个时间内,要执行完当前区域代码,才能释放CPU
            //synchronized (锁对象)
            //锁对象,就是指定程共享的锁对象,被共享的对象就会在执行锁住代码区域中不会被抢占
            //这个程序中一百个糖果是共享数据,所以要锁定糖果对象candy
            synchronized (candy) {
                //如果已经没有糖了,则放弃循环,直接结束活动
                if (candy.getCount() == 0) {
                    System.out.println("糖抢完了,活动结束,请左上角关注+1");
                    //糖抢完了,则跳出循环
                    isCandy=false;
                    break;
                }
                //抢走一颗糖,就糖减一
                candy.setCount(candy.getCount() - 1);
                //通告谁拿到了糖,还剩多少糖
                //使用Thread.currentThread()--放回当前正在执行的线程
                //使用getName()方法来返回线程名称
                System.out.println(Thread.currentThread().getName()
                        + "抢到了糖,还剩" + candy.getCount() + "颗糖……");
            }
        }
   }
}
class CandyNumber {
    //代表糖的数量
    private int count;
    //由于要改变,所以提供方法
    public int getCount() {
        return count;
    }
    public void setCount(int count) {
        this.count = count;
    }
}

运行结果:

java公平买票_配置文件