Java线程间通信

@Android线程间通信

正常情况下,每个子线程完成各自的任务就可以结束了。不过有的时候,我们希望多个线程协同工作来完成某个任务,这时就涉及到了线程间通信了。

本文涉及到的知识点:thread.join(), object.wait(), object.notify()等。

如何让两个线程依次执行?

假设有两个线程,一个是线程 A,另一个是线程 B,两个线程分别依次打印 1-3 三个数字即可。我们来看下代码:

private static void demo1() {
Thread A = new Thread(new Runnable() {
    @Override
    public void run() {
        printNumber("A");
    }
});
Thread B = new Thread(new Runnable() {
    @Override
    public void run() {
        printNumber("B");
    }
});
A.start();
B.start();
}

private static void printNumber(String threadName) {
int i=0;
while (i++ < 3) {
    try {
        Thread.sleep(100);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println(threadName + "print:" + i);
}}

输出是
B print: 1
A print: 1
B print: 2
A print: 2
B print: 3
A print: 3
提示每次输出顺序不一定,但是线程互补影响

那么,如果我们希望 B 在 A 全部打印 完后再开始打印呢?我们可以利用 thread.join() 方法,代码如下:

private static void demo2() {
Thread A = new Thread(new Runnable() {
    @Override
    public void run() {
        printNumber("A");
    }
});
Thread B = new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("B 开始等待 A");
        try {
            A.join();//等待A线程全部执行完,在向下执行
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        printNumber("B");
    }
});
B.start();
A.start();
}

输出结果是
B 开始等待 A
A print: 1
A print: 2
A print: 3
B print: 1
B print: 2
B print: 3
可以看到,线程b只有线程a执行完在执行

那如何让 两个线程按照指定方式有序交叉运行呢?

还是上面那个例子,我现在希望 A 在打印完 1 后,再让 B 打印 1, 2, 3,最后再回到 A 继续打印 2, 3。这种需求下,显然 Thread.join() 已经不能满足了。我们需要更细粒度的锁来控制执行顺序。

private static void demo3() {
Object lock = new Object();
Thread A = new Thread(new Runnable() {
    @Override
    public void run() {
        synchronized (lock) {
            System.out.println("A 1");
            try {
                lock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("A 2");
            System.out.println("A 3");
        }
    }
});
Thread B = new Thread(new Runnable() {
    @Override
    public void run() {
        synchronized (lock) {
            System.out.println("B 1");
            System.out.println("B 2");
            System.out.println("B 3");
            lock.notify();
        }
    }
});
A.start();
B.start();
}

输出结果是
A 1
A waiting…
B 1
B 2
B 3
A 2
A 3

A和B执行完,线程C在开始执行

这时候就需要用CyclicBarrier,CyclicBarrier可以使一定数量的线程反复地在栅栏位置处汇集。当线程到达栅栏位置时将调用await方法,这个方法将阻塞直到所有线程都到达栅栏位置。如果所有线程都到达栅栏位置,那么栅栏将打开,此时所有的线程都将被释放,而栅栏将被重置以便下次使用。

    public static void  main(String args[]) {

    int count = 2;

    CyclicBarrier cyclicBarrier = new CyclicBarrier(count);

    for (int i = 0; i < count; i++) {
        int finalI = i;
        new Thread(() -> {

            System.out.println("线程" + finalI + "开始");
            try {
                Thread.sleep(new Random().nextInt(2000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("线程" + finalI + "结束");
            try {
                cyclicBarrier.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
            System.out.println("所有线程结束");
        }).start();
    }
}

执行结果
线程0开始
线程1开始
线程1结束
线程0结束
所有线程结束
所有线程结束

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值