多线程(巩固练习1)

目录


四个窗口同时进行售票

利用线程进行售票处理

思路:
  1. 利用synchronized(同步)限制进来的线程,避免出现售票异常。

  2. 尽量不要将synchronized放在run()上,while(true)是为了让线程一直进行循环。

class TicketRunnable implements Runnable {
    private int ticket = 1000;
    private int num = 0;

    @Override
    public void run() {
        while (true) {
            //synchronized (this) {   //不能放在方法体上,放在方法体有一个进来要运行1000遍后才会出去
            try {
                Thread.sleep(new Random().nextInt(100));
                boolean flag = this.sale();	//使用调用是为了观看更加方便
                if(!flag){		//获取sale()的booleand值是为判断票是否售完
                    break;		//在sale()方法内使用return;发现不能终止循环
                }				//应该是return不能终止不到run()内循环
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private synchronized boolean sale() {
        if (ticket > 0) {
            this.num++;
            this.ticket--;
            System.out.println(Thread.currentThread().getName() + "已售" + this.num + ",余票:" + this.ticket);
            return true;
        } else {
            System.out.println(Thread.currentThread().getName() + "的票以买完!");
            return false;
        }
    }
}

public class Memo01 {
    public static void main(String[] args) {
        TicketRunnable ticketRunnable = new TicketRunnable();
        new Thread(ticketRunnable, "窗口一").start();
        new Thread(ticketRunnable, "窗口二").start();
        new Thread(ticketRunnable, "窗口三").start();
        new Thread(ticketRunnable, "窗口四").start();
    }
}
结果:
窗口二正在售票,一共已售990,余票:10
窗口三正在售票,一共已售991,余票:9
窗口一正在售票,一共已售992,余票:8
窗口二正在售票,一共已售993,余票:7
窗口四正在售票,一共已售994,余票:6
窗口二正在售票,一共已售995,余票:5
窗口一正在售票,一共已售996,余票:4
窗口三正在售票,一共已售997,余票:3
窗口二正在售票,一共已售998,余票:2
窗口四正在售票,一共已售999,余票:1
窗口二正在售票,一共已售1000,余票:0
窗口三的票以买完!
窗口一的票以买完!
窗口二的票以买完!
窗口四的票以买完!

子线程输出10次,主线程输出100次,循环运行50次

思路及步骤:
  1. 先理清子线程和主线程的关系,和生产者与消费者相似(我个人认为)。

  2. 现将子线程和主线程的输出次数先写出来 ,集中在一个类中进行调用。

子线程:
private boolean flag = true;    //true表示主线程输出完毕,false表示子线程输出完毕

    public synchronized void childThread() throws InterruptedException {
        while (!flag) {             //false表示子线程输出完毕
            this.wait();
        }
        for (int i = 0; i < 10; i++) {      //子线程循环10次,进入等待
            Thread.sleep(100);
            System.out.println(Thread.currentThread().getName() + "****************运行******************:" + i);
        }
        flag = false;
        this.notify();
    }
主线程:
private boolean flag = true;    //true表示主线程输出完毕,false表示子线程输出完毕

  public synchronized void mainThread() throws InterruptedException {
        while (flag) {           //true表示主线程输出完毕
            this.wait();
        }
        for (int i = 0; i < 100; i++) {     //主线程循环100次,进入等待
            Thread.sleep(100);
            System.out.println(Thread.currentThread().getName() + "---------------运行------------------:" + i);
        }
        flag = true;
        this.notify();	//使用notify()和notifyAll()没有区别,试过
    }
  1. 在各自的run()内进行for循环输出50次。
class ChildMessage implements Runnable {
    private Message message;

    public ChildMessage(Message message) {
        this.message = message;     //获取对象实例
    }

    @Override
    public synchronized void run() {
        for (int i = 0; i < 50; i++) {  //线程循环50次
            try {
                this.message.childThread();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

//主线程
class MainMessage implements Runnable {
    private Message message;    //获取对象实例

    public MainMessage(Message message) {
        this.message = message;
    }

    @Override
    public synchronized void run() {
        for (int i = 0; i < 50; i++) {  //线程循环50次
            try {
                this.message.mainThread();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class Message {
    private boolean flag = true;    //true表示主线程输出完毕,false表示子线程输出完毕

    public synchronized void childThread() throws InterruptedException {
        while (!flag) {             //false表示子线程输出完毕
            this.wait();
        }
        for (int i = 0; i < 10; i++) {      //子线程循环10次,进入等待
            Thread.sleep(100);
            System.out.println(Thread.currentThread().getName() + "******运行******:" + i);
        }
        flag = false;
        this.notify();
    }

    public synchronized void mainThread() throws InterruptedException {
        while (flag) {           //true表示主线程输出完毕
            this.wait();
        }
        for (int i = 0; i < 100; i++) {     //主线程循环100次,进入等待
            Thread.sleep(100);
            System.out.println(Thread.currentThread().getName() + "------运行------:" + i);
        }
        flag = true;
        this.notify();
    }
}

public class Circle {
    public static void main(String[] args) {
        Message message = new Message();
        ChildMessage child = new ChildMessage(message);
        MainMessage main = new MainMessage(message);
        new Thread(child, "子线程").start();
        new Thread(main, "主线程").start();
    }
}
结果:

主线程------运行------97
主线程------运行------98
主线程------运行------99
子线程******运行******0
子线程******运行******1
子线程******运行******2
子线程******运行******3
子线程******运行******4
子线程******运行******5
子线程******运行******6
子线程******运行******7
子线程******运行******8
子线程******运行******9
主线程------运行------0
主线程------运行------1
主线程------运行------2
主线程------运行------3

参考:

子线程和主线程循环输出参考处:
https://blog.csdn.net/zhaojw_420/article/details/68939728

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值