【面试题】两个线程交互打印输出A1B2C3D4E5F6G7...23X24Y25Z26

标题【面试题】两个线程交互打印输出A1B2C3D4E5F6G7…23X24Y25Z26

方式一 使用synchronized结合WaitNotify实现

public class SolutionByWaitNotify {
    public static void main(String[] args) throws Exception {
        SolutionByWaitNotify solution = new SolutionByWaitNotify();
        Thread t1 = new Thread(solution::printCharsByWaitNotify);
        Thread t2 = new Thread(solution::printNumsByWaitNotify);
        t1.start();
        t2.start();
    }
    public synchronized void printCharsByWaitNotify(){
        try{
            String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
            for (int i = 0; i < str.length(); i++) {
                System.out.print(str.charAt(i));
                this.notify();//通知唤醒线程,但还没释放锁
                this.wait();//释放锁
            }
        }catch (Exception e){e.printStackTrace();}
    }
    public synchronized void printNumsByWaitNotify(){
        try{
            for (int i = 0; i < 26; i++) {
                System.out.print(i+1);
                this.notify();//通知唤醒线程,但还没释放锁
                this.wait();//释放锁
            }
        }catch (Exception e){e.printStackTrace();}
    }
}

每次输出一条就wait,notify,两个线程交互睡眠,唤醒,实现交互输出

方式二 使用CAS锁实现

public class SolutionByCAS {
    public static void main(String[] args) throws Exception {
        SolutionByCAS solution = new SolutionByCAS();
        Thread t1 = new Thread(solution::printCharsByCAS);
        Thread t2 = new Thread(solution::printNumsByCAS);
        t1.start();
        t2.start();
    }
    AtomicInteger flag = new AtomicInteger(1);  //使用java提供的CAS锁实现
    public void printCharsByCAS() {
        String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        for (int i = 0; i < str.length(); i++) {
            while (flag.get()!=1){}
            System.out.print(str.charAt(i));
            flag.set(0);
        }
    }
    public void printNumsByCAS() {
        for (int i = 0; i < 26; i++) {
            while (flag.get()==1) {}
            System.out.print(i+1);
            flag.set(1);
        }
    }
}

使用的是AtomicInteger这个原子类。连个线程都一直死循环的判断flag是否==1,什么实话等于1了,输出一个数字,什么时候不等于1了输出一个字母。
由于AtomicInteger内部使用的是CAS锁,锁能够保证【可见性】和【原子性】,所以AtomicInteger的状态改变,对其他线程是可见的。

方式三 使用volatile关键字实现

public class SolutionByVolatile {
    public static void main(String[] args) throws Exception {
        SolutionByVolatile solution = new SolutionByVolatile();
        Thread t1 = new Thread(solution::printCharsByVolatile);
        Thread t2 = new Thread(solution::printNumsByVolatile);
        t1.start();
        t2.start();
    }
    volatile boolean flag = true;
    public void printCharsByVolatile() {
        String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        for (int i = 0; i < str.length(); i++) {
            while (!flag){}
            System.out.print(str.charAt(i));
            flag = false;
        }
    }
    public void printNumsByVolatile() {
        for (int i = 0; i < 26; i++) {
            while (flag) {}
            System.out.print(i+1);
            flag = true;
        }
    }
}

和CAS类似,但是这个就没用用到锁,只是给flag加了volatile关键字,保证了flag在两个线程间可见。

方式四 使用一种搞笑得方式实现

public class SolutionByJoke {
    public static void main(String[] args) throws Exception {
        SolutionByJoke solution = new SolutionByJoke();
        Thread t1 = new Thread(solution::printByJoke);
        Thread t2 = new Thread(solution::printByJoke);
        t1.start();
        t2.start();
    }
    int count = 0;
    public synchronized void printByJoke() {
        String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        while (count<52){
            if (count%2==0){
                System.out.print(str.charAt(count/2));
            }else System.out.print((count / 2)+1);
            count++;
        }
    }
}

最后这个是一个搞笑的方式,一本正经的假装没问题。虽然能输出正确的结果,但想想为啥是在搞笑 ~-_-

原创文章 19 获赞 2 访问量 4895

猜你喜欢

转载自blog.csdn.net/qq_34173920/article/details/103937853