多线程按序执行
三个不同的线程 A、B、C 将会共用一个 Foo
实例。
- 线程 A 将会调用
first()
方法 - 线程 B 将会调用
second()
方法 - 线程 C 将会调用
third()
方法
请设计程序,以确保 second()
方法在 first()
方法之后被执行,third()
方法在 second()
方法之后被执行。
解决思路
定义标记,如对应线程的标志为可运行时,线程才可执行。
AtomicInteger 是 Java 并发包 (java.util.concurrent.atomic) 中的一个原子类,用于在多线程环境下安全地操作单个 int 类型的值。它提供了一种无锁的线程安全整数操作方式,性能通常优于使用同步锁的方法。以下是 AtomicInteger 的详细介绍:
基本概念:
- AtomicInteger 封装了一个 int 值,所有对这个值的操作都是原子的。
- 它使用了 CPU 的 CAS(Compare-And-Swap)指令来确保操作的原子性。
- 适用于需要频繁更新单个整数值的多线程场景。
主要方法:
- get(): 获取当前值
- set(int newValue): 设置为给定值
- getAndSet(int newValue): 设置新值并返回旧值
- compareAndSet(int expect, int update): 如果当前值等于预期值,则更新为新值
- getAndIncrement(): 自增并返回旧值
- getAndDecrement(): 自减并返回旧值
- incrementAndGet(): 自增并返回新值
- decrementAndGet(): 自减并返回新值
- getAndAdd(int delta): 加上给定值并返回旧值
- addAndGet(int delta): 加上给定值并返回新值
使用场景:
- 计数器(如请求计数、并发访问计数)
- 序列号生成
- 无锁算法中的版本控制
使用CountDownLatch ,CountDownLatch 是 Java 并发包 (java.util.concurrent) 中的一个同步工具类,用于协调多个线程之间的同步。它允许一个或多个线程等待,直到其他线程完成一组操作后才继续执行
基本概念:
- CountDownLatch 维护一个计数器,这个计数器被初始化为一个正整数,表示需要等待的事件数量。
- 当事件发生时,计数器会递减。
- 线程可以调用 await() 方法阻塞等待,直到计数器变为零。
主要方法:
- countDown():使计数器减 1。当计数器达到零时,所有等待的线程将被释放。
- await():使当前线程等待,直到计数器为零,或者线程被中断。
- await(long timeout, TimeUnit unit):带超时的等待。
- getCount():获取当前的计数。
使用场景:
- 确保某个计算在其需要的所有资源都被初始化之后才执行。
- 确保某个服务在其依赖的所有其他服务都已经启动之后才启动。
- 等待多个并行执行的任务全部完成。
使用原子变量进行标记
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);
}
}