一道题检测多线程基本功!(顺序打印ABC)

一道题检测多线程基本功!(顺序打印ABC)

初阶

题目内容:

有三个线程,线程名称分别为:A,B,C。

要求:使三个线程同时启动,并按顺序打印A,B,C。

注:有的人看到这个题目,直接就是创建三个线程,然后直接调用对应的star()方法,这当然是个坑啦。这里我们可以想到join方法,让A线程跑完,再跑B,B线程跑完再跑C。

public class printABC {
    public static void main(String[] args) {
        Thread a = new Thread(()->{
            System.out.print(Thread.currentThread().getName());
        },"A");

        Thread b = new Thread(()->{
            try {
                a.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.print(Thread.currentThread().getName());
        },"B");

        Thread c = new Thread(()->{
            try {
                b.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.print(Thread.currentThread().getName());
        },"C");
        a.start();
        b.start();
        c.start();
    }
}

看上去是不是超简单?这道题进阶一下再看看。

进阶

题目内容:

还是有三个线程,分别打印A,B,C。

要求:按顺序打印ABC,打印10次,同时启动这三个线程。注意:不要用sleep等变相启动线程的方法。

分析:

  1. 连续打印10次,并且需要有顺序,那么就可以联想到线程间通信来解决这个问题。
  2. 每个线程分别对应打印A、B、C,那么就可以使用数组将他们三个保存起来,称为共享资源,匹配到了,则输出。
  3. 利用数组的特性,那么我们就可以使用对应下标去寻找对应数组中的字母,并且可以实现多次循环,按顺序进行。
  4. 由此看来,三个线程执行的都是相同功能,可以单独写一个类来封装,使得代码简便。
public class SequencePrint {
    public static void main(String[] args) {
        Thread a = new Thread(new Task("A"));
        Thread b = new Thread(new Task("B"));
        Thread c = new Thread(new Task("C"));
        c.start();
        b.start();
        a.start();
    }

    private static class Task implements Runnable{
        //每个线程有唯一标识字段
        private String content;
        //顺序打印的内容:可以循环打印
        private static String[] ARR = {"A","B","C"};
        private static int INDEX;//从数组哪个索引打印

        public Task(String content){
            this.content = content;
        }

        @Override
        public void run() {
            try {
                for (int i = 0; i < 10; i++) {
                    synchronized (ARR) {//三个线程使用同一把锁
                        //从数组索引位置打印,如果当前线程要打印的内容不一致,释放对象锁等待
                        //while循环防止,释放锁之后,该线程再次抢占并向下执行。
                        while (!content.equals(ARR[INDEX])) {
                            ARR.wait();
                        }
                        //如果数组要打印的内容和当前线程要打印的一致,
                        //就打印,并把数组索引切换到一个位置,通知其他线程
                        System.out.print(content);
                        if (INDEX == ARR.length - 1) {
                            System.out.println();
                        }
                        //控制下标始终在0,1,2里面循环
                        INDEX = (INDEX + 1) % ARR.length;
                        //该线程执行完了,唤醒下一个线程向下执行
                        ARR.notifyAll();
                    }
                }
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值