面试题答案
一键面试1. 管理线程资源避免耗尽
在Java流的异步模式下,可以通过ForkJoinPool
来有效管理线程资源。ForkJoinPool
是Java 7引入的一种线程池,特别适合处理分治算法和并行流操作。它使用工作窃取算法,使得线程在完成自己的任务后可以从其他线程的队列中窃取任务,提高了线程的利用率。
以下是一个简单的示例,展示如何使用ForkJoinPool
来控制并行流的线程数量:
import java.util.concurrent.ForkJoinPool;
import java.util.stream.IntStream;
public class ThreadResourceManagement {
public static void main(String[] args) {
// 创建一个固定线程数量的ForkJoinPool
ForkJoinPool forkJoinPool = new ForkJoinPool(4);
// 使用创建的ForkJoinPool执行并行流操作
forkJoinPool.submit(() ->
IntStream.range(0, 100)
.parallel()
.forEach(System.out::println)
).join();
// 关闭ForkJoinPool
forkJoinPool.shutdown();
}
}
在上述代码中,我们创建了一个ForkJoinPool
并指定了线程数量为4。然后,通过submit
方法提交一个包含并行流操作的任务,最后使用join
方法等待任务完成,并在最后关闭ForkJoinPool
。
2. 同步控制确保数据一致性
当多个异步流操作需要共享某些状态时,可以使用Atomic
类或者synchronized
关键字来进行同步控制。
使用Atomic类
Atomic
类提供了原子性操作,能够在多线程环境下安全地更新共享状态。以下是一个示例:
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;
public class SynchronizationWithAtomic {
public static void main(String[] args) {
AtomicInteger sharedCounter = new AtomicInteger(0);
IntStream.range(0, 100)
.parallel()
.forEach(i -> sharedCounter.incrementAndGet());
System.out.println("Final counter value: " + sharedCounter.get());
}
}
在这个例子中,AtomicInteger
确保了incrementAndGet
操作的原子性,即使在并行流的多线程环境下也能保证数据的一致性。
使用synchronized关键字
synchronized
关键字可以用来同步代码块,确保同一时间只有一个线程可以执行该代码块。
public class SynchronizationWithSynchronized {
private static int sharedCounter = 0;
public static void main(String[] args) {
Object lock = new Object();
IntStream.range(0, 100)
.parallel()
.forEach(i -> {
synchronized (lock) {
sharedCounter++;
}
});
System.out.println("Final counter value: " + sharedCounter);
}
}
在上述代码中,我们使用synchronized
关键字同步了对sharedCounter
的更新操作,通过一个Object
实例作为锁对象,保证了在任何时刻只有一个线程可以更新sharedCounter
,从而确保数据的一致性。