传统线程同步通信synchronized

1.典型的生产者消费者问题

    先生产再消费,A生产完后 通知B消费 B消费完后通知A 再生产 依次往复。

 

package com.yanghs.test.pro;

/**
 * @author yanghs
 * @Description:沟通资源
 * @date 2018/3/30 23:49
 */
public class Movie {
    private String pic;
    /*信号灯 true生产者生产 false消费者消费*/
    private boolean flag = true;
    public synchronized void play(String pic) throws InterruptedException {
        if(!flag){
            wait();
        }
        this.pic = pic;
        /*生产完毕 更改信号灯 为消费者*/
        System.out.println("生产完毕");
        this.flag = false;
        this.notify();

    }
    public synchronized void watch() throws InterruptedException {
        if(flag){
            wait();
        }
        System.out.println(pic);
        System.out.println("消费完毕");
        /*t通知生产者*/
        this.notify();
        this.flag = true;
    }
}

关键点 把生产者和消费者抽象为一个类里面 便于加锁和通信  上面是抽象好的一个类

生产者

package com.yanghs.test.pro;

/**
 * @author yanghs
 * @Description:生产者
 * @date 2018/3/30 23:52
 */
public class Player implements Runnable {
    private Movie m;

    public Player(Movie m) {
        this.m = m;
    }

    @Override
    public void run() {
        for(int i=0; i<=20;i++){
            try {
                m.play("aaaaaaaaaa");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

消费者

package com.yanghs.test.pro;

/**
 * @author yanghs
 * @Description:消费者
 * @date 2018/3/30 23:52
 */
public class Watcher implements Runnable {
    private Movie m;

    public Watcher(Movie m) {
        this.m = m;
    }

    @Override
    public void run() {
        for (int i=0; i<=20;i++){
            try {
                m.watch();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

调用者

package com.yanghs.test.pro;

/**
 * @author yanghs
 * @Description:
 * @date 2018/3/30 23:59
 */
public class App {
    public static void main(String[] args) {
        Movie m = new Movie();

        Player p  = new Player(m);
        Watcher w = new Watcher(m);
        new Thread(p).start();
        new Thread(w).start();
    }
}

2.一个面试题

    有主线程和子线程,要求子线程先运行5次 后 主线程运行 5次 依次往复5次

分析:子线程主线程是有运行顺序的 运行顺序可以通过 join 和 synchronized wait notify实现 但是这里又要求 这个动作要循环5次,就是  a>b>a>b... 显然join不符合。所以应该向wait这边靠。

    1)子线程和主线程需要相互通知运行 所以先抽象出逻辑代码 ab的通信,synchronized加在方法上 表示锁定调用这个方法的对象 下面的方法就表示锁定 Business实例化的对象 

对象锁是在一个类的对象上加的的锁,只有一把,不管有几个方法进行了同步。
这些同步方法都共有一把锁,只要一个线程获得了这个对象锁,其他的线程就不能访问该对象的任何一个同步方法。

class Business{
    volatile boolean flag = true;//子线程运行 true
    public synchronized void sub(){
        if(!flag){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        for(int i=0;i<=3;i++){
            System.out.println("子线程"+i);
        }
        flag = false;
        notify();
    }
    public  synchronized void main(){
        if(flag){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        for(int i=0;i<=3;i++){
            System.out.println("主线程"+i);
        }
        flag = true;
        notify();
    }
}

    2)调用

public class TraSynchronized {
    public static void main(String[] args) {
        /*建一个业务*/
        final Business b = new Business();
        /*新建一个子线程 并且开启运行 业务中的sub()*/
        new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i =0 ;i<=5;i++){
                    b.sub();
                }
            }
        }).start();
        /*主线程执行 main()*/
        for(int i =0 ;i<=5;i++){
            b.main();
        }

    }
}

实现效果






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值