Java 中使用两个线程循环打印 1a2b3c4d5e6f 的几种方法总结

目录

一、模拟 CAS(Compare And Swap) 自旋锁来实现

二、使用 synchronized 同步锁实现

三、使用 ReentrantLock 锁实现

四、基于 ReentrantLock 锁使用 CAS 的思想来实现


一、模拟 CAS(Compare And Swap) 自旋锁来实现

//静态的全局变量被创建的所有该类的对象共享,在类的方法中也是共享的
    //所以被所有线程访问和修改,使用需要注意线程的安全性
    static boolean b = true;

    //模拟 CAS(Compare And Swap) 自旋锁来实现
    public static void casTest() {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 1; i < 7; i++) {
                    //使用 where 循环,因为当条件不成立,程序就会在此一直等待
                    while (!b) {}
                    System.out.print(i);
                    b = false;
                }
            }
        });
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (char i = 97; i < 103; i++) {
                    while (b) {}
                    System.out.print(i);
                    b = true;
                }
            }
        });
        t1.start();
        t2.start();
    }

问题总结:

Java 中使用两个线程循环打印 1a2b3c4d5e6f 的几种方法总结_第1张图片

匿名内部类访问外部方法的局部变量会自动添加 final 关键字,常量不能被修改。

对于内部类的使用可以参考Java 中的内部类的定义-CSDN博客

二、使用 synchronized 同步锁实现

//使用 synchronized 同步锁实现
    public static void synchronizedTest() {
        //创建锁的对象,需要该对象是一直保持不变的
        Object o = new Object();
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (o) {
                    for (int i = 1; i < 7; i++) {
                        System.out.print(i);
                        //唤醒一个等待中的线程
                        o.notify();
                        /* 线程等待,在类中自定义 wait 方法,
                        使用 Object 的 wait 方法捕获异常*/
                        ThreadTest.wait(o);
                    }
                    /*一定要在 for 循环跳出之后唤醒另一个等待中的线程,
                    避免最后一次 for 循环判断条件不成立,不再进入循环体,
                    无法唤醒另一个线程,导致程序一直无法停止*/
                    o.notify();
                }
            }
        }, "t1").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (o) {
                    for (char i = 97; i < 103; i++) {
                        System.out.print(i);
                        o.notify();
                        ThreadTest.wait(o);
                    }
                    o.notify();
                }
            }
        }, "t2").start();
    }

三、使用 ReentrantLock 锁实现

//使用 ReentrantLock 锁实现
    public static void reentrantLockTest() {
        /*两个线程都是用同一个 lock 锁
        ReentrantLock是一个可重入的互斥锁,它允许线程多次获得同一把锁。
        这意味着一个线程可以多次调用lock()方法,而不会导致死锁。*/
        Lock lock = new ReentrantLock();
        //建立两个 condition 队列来关联两个线程
        //Condition是用来实现线程间协调的机制。
        Condition c1 = lock.newCondition();
        Condition c2 = lock.newCondition();
        new Thread(() -> {
            try {
                /*lock方法用于获取锁,作用是阻塞当前线程,直到获取到锁为止。
                lock方法可以保证在同一时刻只有一个线程能够获得锁,
                其他线程会被阻塞,直到锁被释放。*/
                lock.lock();
                for (int i = 0; i < numArr.length; i++) {
                    System.out.print(numArr[i]);
                    //唤醒 c2 队列上等待的线程
                    c2.signal();
                    //线程1在 c1 队列上等待
                    c1.await();
                }
                c2.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }, "t1").start();
        new Thread(() -> {
            try {
                lock.lock();
                for (int i = 0; i < letterArr.length; i++) {
                    System.out.print(letterArr[i]);
                    //唤醒 c1 队列上等待的一个线程
                    c1.signal();
                    //线程2在 c2 队列上等待
                    c2.await();
                }
                //避免线程无法跳出for循环的等待
                c2.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //释放锁
                lock.unlock();
            }

        }, "t2").start();
    }

四、基于 ReentrantLock 锁使用 CAS 的思想来实现

 static boolean flag = true;

    //基于 ReentrantLock 锁使用 CAS 的思想来实现
    public static void reentrantLockTestPlus() {
        Lock lock = new ReentrantLock();
        //只用创建一个 condition 队列
        Condition condition = lock.newCondition();
        //创建一个标志
        new Thread(() -> {
            try {
                lock.lock();
                for (int i = 0; i < numArr.length; i++) {
                    //就相当于上述 CAS 中的 while 循环,一直阻塞方法的进行
                    if (!flag) {
                        condition.await();
                    }
                    System.out.print(numArr[i]);
                    flag = false;
                    condition.signal();
                }
                 /*不用在循环体外再去唤醒等待中的线程,因为 await 的过程在 for 判断之后,
                也就是说最后一次 for 判断条件在 await 之前,不会导致程序一直等待结束*/
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }, "t1").start();
        new Thread(() -> {
            try {
                lock.lock();
                for (int i = 0; i < letterArr.length; i++) {
                    if (flag) {
                        condition.await();
                    }
                    System.out.print(letterArr[i]);
                    flag = true;
                    condition.signal();
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }, "t2").start();
    }

你可能感兴趣的:(java,开发语言)