Java多线程之线程协作(线程之间的通信)

本文详细介绍了Java中处理线程同步与通信的三种方法:synchronized关键字、管程法和信号量。通过实例展示了如何使用这些机制解决生产者消费者问题和资源竞争问题,强调了它们在多线程编程中的应用和限制。
摘要由CSDN通过智能技术生成

1、局限

  • synchronized只能解决线程同步问题,不能解决通信问题

2、java提供的方法,解决线程通信问题

方法名作用
wait()表示线程一直等待,直到其他线程通知,和sleep不同,它会释放锁
wait(long timeout)指定等待毫秒数
notify()唤醒一个处于等待的线程
notifyAll()唤醒同一个对象上所有调用wait()方法的线段,优先级别高的线程优先调度
  • 注意:以上方法都是Object类的方法。只能在同步方法和同步代码块中使用。

3、管程法

  • 利用一个缓冲区
生产者消费者例子
  • 缓冲区
//缓冲区
class SynContainer {
    Chicken[] chickens = new Chicken[10];
    int amount = 0;

    //生产商品
    public synchronized void product(Chicken chicken) {

        //满了 停止生产 通知消费者消费
        if (amount == chickens.length) {
            //等待
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //生产
        chickens[amount] = chicken;
        amount++;
        //通知
        this.notifyAll();
    }

    //消费商品
    public synchronized Chicken consume() {
        //空了 停止消费 通知生产者生产
        if (amount == 0) {
            // 等待
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //消费
        amount--;
        Chicken chicken = chickens[amount];
        this.notifyAll();
        //通知
        return chicken;
    }

  • 生产者
//
生产者
class Producor extends Thread {
    SynContainer container;

    public Producor(SynContainer container) {
        this.container = container;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            //加入延时
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            container.product(new Chicken(i));
            System.out.println("生产了第" + (i+1) + "只鸡");
        }
    }
}
  • 消费者
//消费者
class Consumer extends Thread {
    SynContainer container;

    public Consumer(SynContainer container) {
        this.container = container;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            //加入延时
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("消费了-->第" + (container.consume().id + 1) + "只鸡");
        }
    }
}
  • 商品
//商品 - 炸鸡
class Chicken {
    int id;

    public Chicken(int id) {
        this.id = id;
    }
}
  • 调度
public static void main(String[] args) {
    SynContainer container = new SynContainer();
    //生产者
    new Producor(container).start();
    //加入延时
    try {
        Thread.sleep(100);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    //消费者
    new Consumer(container).start();
}

4、信号量

  • 利用一个标志位
public class DWTest {
    public static void main(String[] args) {
        Car car = new Car();
        new Drive(car).start();
        new WashCar(car).start();
    }
}

//去洗车
class WashCar extends Thread {
    Car car;

    public WashCar(Car car) {
        this.car = car;
    }

    @Override
    public void run() {
        for (int i = 1; i < 30; i++) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            car.wash(i);
        }
    }
}

//开车(取车)
class Drive extends Thread {
    Car car;

    public Drive(Car car) {

        this.car = car;
    }

    @Override
    public void run() {
        //一个月
        for (int i = 1; i < 30; i++) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            car.drive(i);
        }
    }
}

//车
class Car {
    //初始表示不洗车
    boolean flag = false;

    public synchronized void drive(int days) {

        if (flag) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        System.out.println("开车中。。。。。。");
        System.out.println("第" + days + "天该洗车了");
        this.flag = !this.flag;
        this.notifyAll();

    }

    public synchronized void wash(int days) {
        if (!flag) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.flag = !this.flag;
        this.notifyAll();
        System.out.println("洗好了");

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值