1. 铁道部发布了一个售票任务,要求销售1000张票,要求有10个窗口来进行销售,请编写多线程程序来模拟这个效果 iv.窗口001正在销售第1000张票 v.窗口001正在销售第999张票

最近遇到一个售票系统的题目,我用了3种方法逐渐完善,希望能对您有所帮助,如有不当敬请指出。
不加锁Runnable版

package com.qf.a_safe;
/**
 *  1. 铁道部发布了一个售票任务,要求销售1000张票,要求有10个窗口来进行销售,请编写多线程程序来模拟这个效果
    iv.窗口001正在销售第1000张票
    v.窗口001正在销售第999张票
    vi.窗口002正在销售第998张票
    vii.。。。
    viii.窗口010正在销售第1张票
    ix.票已经销售完毕
 *
 */
/**
 * 不加锁Runnable版
 *
 */

class Task2 implements Runnable{
    private int ticket2 = 1000;//1000张票
    @Override
    public void run() {
        //while (true){}可以避免"票已经销售完毕"打印次数少的状况
        while (true) {
            if (ticket2>0) {
                System.out.println(Thread.currentThread().getName() +"正在销售第"+ticket2+"张票");
                ticket2--;  
            } else {
                System.out.println(Thread.currentThread().getName() +"票已经销售完毕");
                break;
            }           
        }           
    }   
}

public class Test1_2 {
    public static void main(String[] args) {
        Task2 task2 = new Task2();
        for (int i = 1; i <= 10; i++) { 
            if (i<=9) {
                //这里需要注意,若不先new Task2()直接写new Thread(new task2,"窗口00"+i).start();
                //会出现每个线程都卖1000张票的情况,因为对象不唯一会导致每个线程对象都有一份独立的成员属性;
                new Thread(task2,"窗口00"+i).start();
            } else {
                new Thread(task2,"窗口010").start();
            }
        }
    }
}

不加锁Thread版本

class MyTread2 extends Thread{
    //用static修饰来保证ticket3的唯一性,Runnable中不用static修饰是因为Task2对象唯一
    private static int ticket3 = 1000;

    public MyTread2(String name) {
        super(name);
    }

    @Override
    public void run() {
        while (true) {
            if (ticket3>0) {
                System.out.println(this.getName() +"正在销售第"+ticket3+"张票");
                ticket3--;  
            } else {
                System.out.println(this.getName() +"票已经销售完毕");
                break;
            }           
        }           
    }   
}

public class Test_3 {
    public static void main(String[] args) {        
        for (int i = 1; i <= 10; i++) { 
            if (i<=9) {
                new MyTread2("窗口00"+i).start();         
            } else {
                new MyTread2("窗口010").start();
            }
        }
    }
}

锁对象Runnable版本

package com.qf.a2_safe;

class Task implements Runnable{
    private int ticket = 1000;//因为对象只有一个


    @Override
    public void run() {
        synchronized (this) {//因为对象只有一个
            while (true) {
                if (ticket>0) {
                    System.out.println(Thread.currentThread().getName()+"卖出"+ticket+"张票");
                    ticket--;
                } else {
                    System.out.println(Thread.currentThread().getName()+"票已卖完");
                    break;
                }
            }
        }               
    }
}

public class Suo {
    public static void main(String[] args) {
        Task task = new Task();
        for (int i = 1; i <= 10; i++) { 
            if (i<=9) {
                //这里需要注意,若不先new Task2()直接写new Thread(new task2,"窗口00"+i).start();
                //会出现每个线程都卖1000张票的情况,因为对象不唯一会导致每个线程对象都有一份独立的成员属性;
                new Thread(task,"窗口00"+i).start();
            } else {
                new Thread(task,"窗口010").start();

            }
        }
    }
}

对象锁Thread版本

package com.qf.a_safe;

/**
 * 1. 铁道部发布了一个售票任务,要求销售1000张票,要求有5个窗口来进行销售,请编写多线程程序来模拟这个效果
    iv.窗口001正在销售第1000张票
    v.窗口001正在销售第999张票
    vi.窗口002正在销售第998张票
    vii.。。。
    viii.窗口05正在销售第1张票
    ix.票已经销售完毕

   目标:  
    方式1: 继承Thread,创建线程
    方式2: 实现Runnable接口

    通过案例分析:    继承Thread  VS  Runnable

    使用方式1分析案例:
    问题1: 每个窗口都卖了1000张票
    原因:  每个线程对象都有一份独立的成员属性(1000张票)
    处理:  变为静态属性

    问题2: 有部分重票
    原因:  多个线程抢占资源,一个线程打印票没进行--操作,另一个线程又打印了
    处理: 加锁----如何加锁---
         加锁方式有3种: 1. 同步代码块   2. 同步方法   3,对象互斥锁(容易出现死锁)
         加锁的注意事项: 1.确保是同一把锁   2. 锁的范围    

    问题3: 出现负数的问题
    原因:   判断出现问题,
    处理:   在同步锁内部继续加判断  

    继续优化:有多少窗口卖票,就应该要有多少窗口退出
    解决方案:  while(true){} ,然后从一个出口退出                      
 *
 */
/**
 * 锁对Thread象版
 *
 */
class MyThread12 extends Thread{
    private static int ticket = 1000;  //销售1000张票
    private static Object obj = new Object();

    public MyThread12(String name) {
        super(name);
    }

    @Override
    public void run() {

        while(true){ 
            //锁对象,要确保是同一把锁(同一个对象)
            synchronized ("lock"/*obj*/) {  //静态属性:obj,字符串常量
                if(ticket>0){
                    System.out.println(super.getName()+"正在销售第"+ticket+"张票");
                    ticket--;
                }else{
                    System.out.println(super.getName()+"票已经销售完毕");
                    break;
                }
            }
        }

    }
}

public class Test1 {
    public static void main(String[] args) {
        for (int i = 1; i <= 10; i++) { 
            if (i<=9) {
                new MyThread12("窗口00"+i).start();           
            } else {
                new MyThread12("窗口010").start();
            }
        }
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值