例题讲解-两个线程间通信-依次输出12A34B56C......

3 篇文章 0 订阅
2 篇文章 0 订阅

例题:线程A输出1-52,线程B输出A-Z,最后的输出结果是:12A34B56C…。

首先要想依次输出,需要实现两个线程之间的通信,线程之间的通讯可以通过共享对象来实现
思路:两个线程A,B都实现Runnable接口,在C线程的main方法中,定义一个Object变量,并且将这个Object变量传入到A,B的构造方法中,当创建A,B两个线程的时候,通过有参的构造方法创建,在for循环中添加同步代码块,在A线程中,执行两次循环,让该线程休眠并唤醒别的线程(这里写代码时候,是先唤醒notifyAll(),然后wait()),B线程中是执行一次循环,就让线程休眠并唤醒其他线程。

不过这个思路有一个不足,就是不一定会先输出数字,因为A,B不知道谁会先抢到CPU。此时,可以通过创建一个具有属性的对象,利用对象中的属性来进行判断,比如创建了一个Foo对象,Foo有一个属性“x=1”,当x=1的时候,才进行执行A线程。如果B先抢到了CPU,此时判断x!=1,那么就让B线程修眠。

以Object为共享对象的代码实现

class A implements Runnable{
    private Object obj;

    public A(Object obj){
        this.obj = obj;
    }

    @Override
    public void run() {
        synchronized (obj){
            for (int i=1;i<=52;i++){
                System.out.println(i);
                if(i%2==0){
                    obj.notifyAll();
                    try {
                        obj.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}
class B implements Runnable{
    private Object obj;

    public B(Object obj){
        this.obj = obj;
    }

    @Override
    public void run() {
        synchronized (obj){
            for (int i='A';i<='Z';i++){
                System.out.println((char)i);
                obj.notifyAll();
                try {
                    obj.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
public class C {
    public static void main(String[] args) {
        Object obj = new Object();

        A a = new A(obj);
        B b = new B(obj);

        Thread t1 = new Thread(a);
        Thread t2 = new Thread(b);
        t1.start();
        t2.start();
    }
}

以Foo为共享对象的代码实现

class Foo{
    public int x = 1;
}
class A implements Runnable{
    private Foo foo;

    public A(Foo foo){
        this.foo = foo;
    }

    @Override
    public void run() {
        synchronized (foo){
            /*
            这里要想输出Z,则i<=53,
            因为当输出完52的时候,i++则会变为53,
            此时for循环就结束了,就不会执行唤醒线程,所以没有办法输出Z,
            但是这样的话,线程总会有线程是阻塞状态,
            所以另一种办法就是通过判断,
            即当执行到52或者Z的时候,不再用wait()
            本代码中使用的是第二种办法
             */
            for (int i=1;i<=52;i++){
                while (foo.x!=1){
                    foo.notifyAll();
                    try {
                        foo.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(i);
                if(i%2==0){
                    foo.x=2;
                }
                if(i==52){
                    foo.notifyAll();
                }

            }
        }
    }
}
class B implements Runnable{
    private Foo foo;

    public B(Foo foo){
        this.foo = foo;
    }

    @Override
    public void run() {
        synchronized (foo){
            for (int i='A';i<='Z';i++){
                while (foo.x!=2){
                    foo.notifyAll();
                    try {
                        foo.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println((char)i);
                foo.x=1;
                if(i=='Z'){
                    foo.notifyAll();
                }

            }
        }
    }
}
public class C {
    public static void main(String[] args) {
        Foo foo = new Foo();

        A a = new A(foo);
        B b = new B(foo);

        Thread t1 = new Thread(a);
        Thread t2 = new Thread(b);

        t2.start();
        t1.start();
    }
}

其实在视频课上并没有发现按照老师的代码输出不了Z,并不是说老师教的不好或者怎么样,老师也是偶然想到,才引申出优化的那一个实现。
是自己觉得,学习了java这么久,第一次觉得,对待编程要认真,严谨,要去思考解决思路,最主要是自己动脑思考,并且要努力实践。这样才会发现其中的乐趣。
还有要努力钻研。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值