多线程按序执行

三个不同的线程 A、B、C 将会共用一个 Foo 实例。

  • 线程 A 将会调用 first() 方法
  • 线程 B 将会调用 second() 方法
  • 线程 C 将会调用 third() 方法

请设计程序,以确保 second() 方法在 first() 方法之后被执行,third() 方法在 second() 方法之后被执行。

解决思路

  1. 定义标记,如对应线程的标志为可运行时,线程才可执行。

    AtomicInteger 是 Java 并发包 (java.util.concurrent.atomic) 中的一个原子类,用于在多线程环境下安全地操作单个 int 类型的值。它提供了一种无锁的线程安全整数操作方式,性能通常优于使用同步锁的方法。以下是 AtomicInteger 的详细介绍:

    1. 基本概念:

      • AtomicInteger 封装了一个 int 值,所有对这个值的操作都是原子的。
      • 它使用了 CPU 的 CAS(Compare-And-Swap)指令来确保操作的原子性。
      • 适用于需要频繁更新单个整数值的多线程场景。
    2. 主要方法:

      • get(): 获取当前值
      • set(int newValue): 设置为给定值
      • getAndSet(int newValue): 设置新值并返回旧值
      • compareAndSet(int expect, int update): 如果当前值等于预期值,则更新为新值
      • getAndIncrement(): 自增并返回旧值
      • getAndDecrement(): 自减并返回旧值
      • incrementAndGet(): 自增并返回新值
      • decrementAndGet(): 自减并返回新值
      • getAndAdd(int delta): 加上给定值并返回旧值
      • addAndGet(int delta): 加上给定值并返回新值
    3. 使用场景:

      • 计数器(如请求计数、并发访问计数)
      • 序列号生成
      • 无锁算法中的版本控制
  2. 使用CountDownLatch ,CountDownLatch 是 Java 并发包 (java.util.concurrent) 中的一个同步工具类,用于协调多个线程之间的同步。它允许一个或多个线程等待,直到其他线程完成一组操作后才继续执行

    1. 基本概念:

      • CountDownLatch 维护一个计数器,这个计数器被初始化为一个正整数,表示需要等待的事件数量。
      • 当事件发生时,计数器会递减。
      • 线程可以调用 await() 方法阻塞等待,直到计数器变为零。
    2. 主要方法:

      • countDown():使计数器减 1。当计数器达到零时,所有等待的线程将被释放。
      • await():使当前线程等待,直到计数器为零,或者线程被中断。
      • await(long timeout, TimeUnit unit):带超时的等待。
      • getCount():获取当前的计数。
    3. 使用场景:

      • 确保某个计算在其需要的所有资源都被初始化之后才执行。
      • 确保某个服务在其依赖的所有其他服务都已经启动之后才启动。
      • 等待多个并行执行的任务全部完成。
使用原子变量进行标记
public class ThA {

    static class Foo {

        public Foo() {
        }

        private final AtomicInteger third = new AtomicInteger(0);
        private final AtomicInteger second = new AtomicInteger(0);

       
        public void first() {
            System.out.println("first");
            second.incrementAndGet();
        }

        public void second() {
            while (second.get() != 1) {

            }
            System.out.println("second");
            second.incrementAndGet();
            
        }

        public void third() {
            while (third.get() != 1) {

            }
            System.out.println("third");
        }
    }

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        Foo foo = new Foo();
        Thread thread1 = new Thread(foo::first);
        Thread thread2 = new Thread(foo::second);
        Thread thread3 = new Thread(foo::third);
        thread1.start();
        thread2.start();
        thread3.start();

        try {
            thread1.join();
            thread2.join();
            thread3.join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        long endTime = System.currentTimeMillis();
        long duration = endTime - startTime;
        System.out.println("开始: " + startTime);
        System.out.println("结束: " + endTime);
        System.out.println("程序执行时间(毫秒): " + duration);

    }
}
CountDownLatch同步工具类
public class ThA {

    static class Foo {

        public Foo() {
        }

        private final CountDownLatch thirdDown = new CountDownLatch(1);
        private final CountDownLatch secondDown = new CountDownLatch(1);

        public void first() {
            System.out.println("first");
            secondDown.countDown();
        }

        public void second() {
            try {
                secondDown.await();
                System.out.println("second");
                secondDown.countDown();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

        }

        public void third() {
            try {
                thirdDown.await();
                System.out.println("third");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        Foo foo = new Foo();
        Thread thread1 = new Thread(foo::first);
        Thread thread2 = new Thread(foo::second);
        Thread thread3 = new Thread(foo::third);
        thread1.start();
        thread2.start();
        thread3.start();

        try {
            thread1.join();
            thread2.join();
            thread3.join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        long endTime = System.currentTimeMillis();
        long duration = endTime - startTime;
        System.out.println("开始: " + startTime);
        System.out.println("结束: " + endTime);
        System.out.println("程序执行时间(毫秒): " + duration);

    }
}
最后修改:2024 年 10 月 04 日
如果觉得我的文章对你有用,请随意赞赏