Java线程基础实战
CPU核数
查看代码
# CPU核数指CPU的物理核心数量,每个核心可独立执行指令。
# CPU核数就像工厂里的工人数量。每个核心就是一个独立的工人,能够同时处理不同的任务。现代CPU通常有2-16个核心,高端服务器可能有几十个核心。
# 核心越多,CPU并行处理任务的能力越强。例如,4核CPU可同时处理4个独立任务。
# Core(s) per socket(每插槽核心数)和Socket(s)(插槽数,总核数=核心数×插槽数)
[root@hadoop ~]# lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 8
On-line CPU(s) list: 0-7
Thread(s) per core: 1
Core(s) per socket: 8
Socket(s): 1
NUMA node(s): 1
Vendor ID: GenuineIntel
CPU family: 6
Model: 158
Model name: Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz
Stepping: 13
CPU MHz: 800.024
CPU max MHz: 4900.0000
CPU min MHz: 800.0000
BogoMIPS: 7200.00
Virtualization: VT-x
L1d cache: 32K
L1i cache: 32K
L2 cache: 256K
L3 cache: 12288K
NUMA node0 CPU(s): 0-7
Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch invpcid_single ssbd rsb_ctxsw ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear spec_ctrl intel_stibp flush_l1d arch_capabilities
线程
查看代码
/**
* 1. 线程是CPU核心通过超线程技术(Hyper-Threading)模拟的逻辑执行单元。一个物理核心可支持多个线程(通常2个)。
* 超线程允许核心在等待I/O或内存时切换到另一线程,提高资源利用率,但不等同于额外物理核心。
*
* 2. 线程有两个层面的含义:
* 2.1 硬件线程:现代CPU支持超线程技术,一个物理核心可以同时处理2个线程,就像一个熟练工人可以同时用左右手做不同的工作。
* 2.2 软件线程:程序中创建的执行单元,就像给工人分配的具体任务。
*
* 3. 总逻辑核心数=核数×每核心线程数
* 核数__Core(s) per socket:lscpu | grep "Core(s)"
* 每核心线程数__Thread(s) per core: lscpu | grep "Core(s) per socket"
*
* 4. 应用场景(注意:过多线程导致切换开销,过少线程浪费核心资源。)
* CPU密集型(如计算):线程数≈核数,避免上下文切换
* I/O密集型(如网络请求):线程数可为2×核数,利用等待时间。
* 4.1 Tomcat服务器:<Executor name="tomcatThreadPool" maxThreads="2×核数" />
* 4.2 批处理任务:
* // 对象字段排序
* List<Person> sorted = people.parallelStream()
* .sorted(Comparator.comparing(Person::getAge))
* .collect(Collectors.toList());
* 4.3 部署优化:
* Docker限制CPU:docker run --cpus="4" myAppliccation
* JVM参数优化: java -Xmx2g -XX:+UseParallelGC -jar Test.jar
* 4.4 性能监控:
* 使用htop或Java VisualVM监控线程与CPU使用
* 检查top -H输出,定位高CPU线程
*
**/
public class Test {
public static void main(String[] args) {
// 逻辑核心数
System.out.println(Runtime.getRuntime().availableProcessors());
}
}
创建线程方法
| 继承线程类 | java.lang.Thread |
| 实现接口 | java.lang.Runnable、java.lang.Callable、java.lang.FutureTask |
| 线程池 |
java.util.concurrent.ThreadPoolExecutor
|
线程数量与CPU核数关系
CPU密集型:
特征:大量计算,很少等待
表现:CPU使用率高,内存/磁盘使用率低
例子:数学运算、图像处理、加密解密
线程策略:线程数 = CPU核数(避免上下文切换)
I/O密集型
特征:频繁等待,少量计算
表现:CPU使用率低,大量时间等待I/O
例子:文件读写、网络请求、数据库查询
线程策略:线程数 = CPU核数 × 2 至 CPU核数 × 4
实验

查看代码
查看代码
package org.asyncProgramming;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class ThreadPerformanceTest {
public static void main(String[] args) {
System.out.println(Runtime.getRuntime().availableProcessors());
System.out.println("=== CPU密集型任务测试 ===");
testCPUIntensiveTask();
System.out.println("\n=== I/O密集型任务测试 ===");
testIOIntensiveTask();
System.out.println("\n=== 混合型任务测试 ===");
testMixedTask();
}
// CPU密集型任务测试
private static void testCPUIntensiveTask() {
System.out.println("CPU密集型任务 - 计算密集运算");
int[] threadCounts = {2, 4, 8, 16, 32, 64, 128, 256};
int taskCount = 10000; // 固定任务数量
for (int threadCount : threadCounts) {
long startTime = System.currentTimeMillis();
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
CountDownLatch latch = new CountDownLatch(taskCount);
for (int i = 0; i < taskCount; i++) {
final int taskId = i;
executor.submit(() -> {
// CPU密集型计算:计算素数
int count = 0;
for (int num = 2; num <= 100000; num++) {
if (isPrime(num)) {
count++;
}
}
// System.out.println("任务" + taskId + "完成,找到" + count + "个素数 [线程: " + Thread.currentThread().getName() + "]");
latch.countDown();
});
}
try {
latch.await();
executor.shutdown();
executor.awaitTermination(1, TimeUnit.MINUTES);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
long endTime = System.currentTimeMillis();
System.out.println("线程数: " + threadCount + ", 耗时: " + (endTime - startTime) + "ms");
}
}
// I/O密集型任务测试
private static void testIOIntensiveTask() {
System.out.println("I/O密集型任务 - 模拟网络请求");
int[] threadCounts = {2, 4, 8, 16, 32, 64, 128, 256};
int taskCount = 12; // 固定任务数量
for (int threadCount : threadCounts) {
long startTime = System.currentTimeMillis();
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
CountDownLatch latch = new CountDownLatch(taskCount);
for (int i = 0; i < taskCount; i++) {
final int taskId = i;
executor.submit(() -> {
try {
// 模拟I/O等待时间
Thread.sleep(1000);
// System.out.println("任务" + taskId + "完成 [线程: " + Thread.currentThread().getName() + "]");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
latch.countDown();
});
}
try {
latch.await();
executor.shutdown();
executor.awaitTermination(1, TimeUnit.MINUTES);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
long endTime = System.currentTimeMillis();
System.out.println("线程数: " + threadCount + ", 耗时: " + (endTime - startTime) + "ms");
}
}
// 混合型任务测试
private static void testMixedTask() {
System.out.println("混合型任务 - CPU计算 + I/O等待");
int[] threadCounts = {2, 4, 8, 16, 32, 64, 128, 256};
int taskCount = 8; // 固定任务数量
for (int threadCount : threadCounts) {
long startTime = System.currentTimeMillis();
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
CountDownLatch latch = new CountDownLatch(taskCount);
for (int i = 0; i < taskCount; i++) {
final int taskId = i;
executor.submit(() -> {
try {
// CPU计算部分
int count = 0;
for (int num = 2; num <= 10000; num++) {
if (isPrime(num)) {
count++;
}
}
// I/O等待部分
Thread.sleep(500);
// System.out.println("任务" + taskId + "完成,找到" + count + "个素数 [线程: " + Thread.currentThread().getName() + "]");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
latch.countDown();
});
}
try {
latch.await();
executor.shutdown();
executor.awaitTermination(1, TimeUnit.MINUTES);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
long endTime = System.currentTimeMillis();
System.out.println("线程数: " + threadCount + ", 耗时: " + (endTime - startTime) + "ms");
}
}
// 判断是否为素数的辅助方法
private static boolean isPrime(int n) {
if (n <= 1) return false;
if (n <= 3) return true;
if (n % 2 == 0 || n % 3 == 0) return false;
for (int i = 5; i * i <= n; i += 6) {
if (n % i == 0 || n % (i + 2) == 0) return false;
}
return true;
}
}
实验结果
查看代码
查看代码
D:\opt\soft\dev\jdk\jdk-21.0.6\bin\java.exe -javaagent:D:\opt\soft\dev\idea\lib\idea_rt.jar=49211 -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -classpath D:\opt\workspace\java\HashConflict\target\classes org.asyncProgramming.ThreadPerformanceTest
16
=== CPU密集型任务测试 ===
CPU密集型任务 - 计算密集运算
线程数: 2, 耗时: 6032ms
线程数: 4, 耗时: 3148ms
线程数: 8, 耗时: 1867ms
线程数: 16, 耗时: 1415ms
线程数: 32, 耗时: 1460ms
线程数: 64, 耗时: 1412ms
线程数: 128, 耗时: 1426ms
线程数: 256, 耗时: 1430ms
=== I/O密集型任务测试 ===
I/O密集型任务 - 模拟网络请求
线程数: 2, 耗时: 6032ms
线程数: 4, 耗时: 3016ms
线程数: 8, 耗时: 2011ms
线程数: 16, 耗时: 1004ms
线程数: 32, 耗时: 1014ms
线程数: 64, 耗时: 1008ms
线程数: 128, 耗时: 1007ms
线程数: 256, 耗时: 1005ms
=== 混合型任务测试 ===
混合型任务 - CPU计算 + I/O等待
线程数: 2, 耗时: 2043ms
线程数: 4, 耗时: 1025ms
线程数: 8, 耗时: 513ms
线程数: 16, 耗时: 512ms
线程数: 32, 耗时: 511ms
线程数: 64, 耗时: 510ms
线程数: 128, 耗时: 511ms
线程数: 256, 耗时: 511ms
进程已结束,退出代码为 0
线程同步
为什么需要线程同步?
真实的业务痛点
查看代码
// 电商平台的秒杀场景:1000个用户同时抢购10件商品,如果没有合适的同步机制,就会出现如下危险的库存扣减代码
public class UnsafeInventory {
private int stock = 10;
public boolean purchase() {
if (stock > 0) { // 步骤1:检查库存 (问题:多个线程可能同时通过该步骤检查,导致库存被"超卖"。)
// 模拟网络延迟
Thread.sleep(10);
stock--; // 步骤2:扣减库存
return true;
}
return false;
}
}
并发问题的本质
- 可见性:线程A修改了变量,线程B看不到
- 使用volatile关键字;使用同步机制;使用并发工具类
- 原子性:操作被中断,导致数据不一致
- 使用原子操作类;使用同步锁;使用CAS操作;
- 有序性:编译器重排序破坏了程序逻辑
基础同步机制
1. synchronized
public class SafeInventory {
private int stock = 10;
// 业务价值:确保库存扣减的原子性,彻底解决超卖问题。
public synchronized boolean purchase() {
if (stock > 0) {
stock--;
return true;
}
return false;
}
}
// 优化:减小锁粒度,提高并发性能。
public class OptimizedOrderService {
private final Object lockObj = new Object();
private long sequence = 0;
public String processOrder(Order order) {
// 业务逻辑处理(不需要同步)
validateOrder(order);
calculatePrice(order);
// 只对关键部分加锁
synchronized (lockObj) {
order.setOrderNumber(generateSequence());
saveOrder(order);
}
// 后续处理(不需要同步)
sendNotification(order);
return order.getOrderNumber();
}
}
2. volatile轻量级同步
// 业务场景:系统开关控制
public class SystemController {
private volatile boolean maintenanceMode = false;
// 业务请求处理
public void handleRequest(Request request) {
if (maintenanceMode) {
throw new ServiceUnavailableException("系统维护中");
}
// 正常处理请求
processRequest(request);
}
// 运维操作
public void enableMaintenanceMode() {
maintenanceMode = true; // 立即对所有线程可见
}
}
// 经典应用:双重检查锁单例
// 使用场景:状态标志变量;配置热更新;单例模式优化
public class ConfigManager {
private static volatile ConfigManager instance;
private Properties config;
private ConfigManager() {
// 加载配置文件
loadConfig();
}
public static ConfigManager getInstance() {
if (instance == null) {
synchronized (ConfigManager.class) {
if (instance == null) {
instance = new ConfigManager();
}
}
}
return instance;
}
}
3. Lock接口:更灵活的同步机制
// 可中断锁:优雅处理超时
public class PaymentService {
private final Lock paymentLock = new ReentrantLock();
public boolean processPayment(PaymentRequest request) {
try {
// 尝试获取锁,最多等待3秒
if (paymentLock.tryLock(3, TimeUnit.SECONDS)) {
try {
return doPayment(request);
} finally {
paymentLock.unlock();
}
} else {
// 超时处理
throw new PaymentTimeoutException("支付系统繁忙,请稍后重试");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
// 读写锁:读操作并发执行,写操作独占访问,显著提升读多写少场景的性能。
public class ProductCacheService {
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final Map<String, Product> cache = new HashMap<>();
// 高并发读操作
public Product getProduct(String productId) {
lock.readLock().lock();
try {
return cache.get(productId);
} finally {
lock.readLock().unlock();
}
}
// 低频写操作
public void updateProduct(Product product) {
lock.writeLock().lock();
try {
cache.put(product.getId(), product);
// 通知缓存更新
notifyUpdateListeners(product);
} finally {
lock.writeLock().unlock();
}
}
}
4. 线程同步工具类(CountDownLatch、Semaphore、CyclicBarrier)
// CountDownLatch:等待子任务完成
public class ReportGeneratorService {
private final ExecutorService executor = Executors.newFixedThreadPool(5);
public Report generateMonthlyReport(String month) {
CountDownLatch latch = new CountDownLatch(4);
// 并行生成报表的各个部分
CompletableFuture<SalesData> salesFuture = CompletableFuture.supplyAsync(() -> {
try {
return generateSalesData(month);
} finally {
latch.countDown();
}
}, executor);
CompletableFuture<UserData> userFuture = CompletableFuture.supplyAsync(() -> {
try {
return generateUserData(month);
} finally {
latch.countDown();
}
}, executor);
// 等待所有子任务完成
try {
latch.await(30, TimeUnit.SECONDS);
return new Report(salesFuture.get(), userFuture.get());
} catch (Exception e) {
throw new ReportGenerationException("报表生成失败", e);
}
}
}
// Semaphore:接口限流
public class ApiRateLimiter {
private final Semaphore semaphore;
public ApiRateLimiter(int maxConcurrentRequests) {
this.semaphore = new Semaphore(maxConcurrentRequests);
}
public ApiResponse processRequest(ApiRequest request) {
try {
// 尝试获取许可证
if (semaphore.tryAcquire(100, TimeUnit.MILLISECONDS)) {
try {
return handleRequest(request);
} finally {
semaphore.release();
}
} else {
return ApiResponse.rateLimited("请求过于频繁,请稍后重试");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return ApiResponse.error("请求被中断");
}
}
}
// CyclicBarrier:分阶段处理
public class BatchDataProcessor {
private final CyclicBarrier barrier;
private final int workerCount;
public BatchDataProcessor(int workerCount) {
this.workerCount = workerCount;
this.barrier = new CyclicBarrier(workerCount, () -> {
System.out.println("所有工作线程完成当前阶段,开始下一阶段");
});
}
public void processData(List<DataRecord> records, int workerId) {
try {
// 第一阶段:数据清洗
cleanData(records, workerId);
barrier.await(); // 等待所有线程完成清洗
// 第二阶段:数据转换
transformData(records, workerId);
barrier.await(); // 等待所有线程完成转换
// 第三阶段:数据保存
saveData(records, workerId);
barrier.await(); // 等待所有线程完成保存
} catch (Exception e) {
throw new DataProcessingException("数据处理失败", e);
}
}
}
5. 原子操作类(AtomicInteger、AtomicBoolean、AtomicLong、AtomicReference)
// 网站访问统计
public class WebsiteAnalytics {
private final AtomicLong totalPageViews = new AtomicLong(0);
private final AtomicLong uniqueVisitors = new AtomicLong(0);
private final ConcurrentHashMap<String, Boolean> visitedUsers = new ConcurrentHashMap<>();
public void recordPageView(String userId) {
// 总页面浏览量
totalPageViews.incrementAndGet();
// 独立访客统计
if (visitedUsers.putIfAbsent(userId, true) == null) {
uniqueVisitors.incrementAndGet();
}
}
public AnalyticsData getAnalytics() {
return new AnalyticsData(
totalPageViews.get(),
uniqueVisitors.get(),
visitedUsers.size()
);
}
}
// 高性能计数器
public class PerformanceCounter {
private final LongAdder successCount = new LongAdder();
private final LongAdder failureCount = new LongAdder();
private final LongAdder totalResponseTime = new LongAdder();
public void recordSuccess(long responseTime) {
successCount.increment();
totalResponseTime.add(responseTime);
}
public void recordFailure() {
failureCount.increment();
}
public PerformanceMetrics getMetrics() {
long success = successCount.sum();
long failure = failureCount.sum();
long totalTime = totalResponseTime.sum();
return new PerformanceMetrics(
success,
failure,
success > 0 ? totalTime / success : 0 // 平均响应时间
);
}
}
性能优化和最佳实践
// 错误:锁粒度过大
public synchronized void badMethod() {
doSomething(); // 不需要同步
updateSharedData(); // 需要同步
doSomethingElse(); // 不需要同步
}
// 正确:减小锁粒度
public void goodMethod() {
doSomething();
synchronized(this) {
updateSharedData(); // 只同步必要部分
}
doSomethingElse();
}
import java.util.concurrent.TimeUnit;
/**
* 死锁demo
* 两个或两个以上的线程互相持有对方需要的锁,导致程序无法正常运行
* 产生原因:同步代码块嵌套同步代码块
* 排查方法:
* <1> jps -l // 查找出进程号
* <2> jstack 进程号
*/
public class DeadLockDemo {
public static void main(String[] args) {
String obj1 = "AA";
String obj2 = "BB";
new Thread(new DeadLockResource(obj1, obj2), "AA").start();
new Thread(new DeadLockResource(obj2, obj1), "BB").start();
}
}
class DeadLockResource implements Runnable {
private final String lockObj1;
private final String lockObj2;
public DeadLockResource(String lockObj1, String lockObj2) {
this.lockObj1 = lockObj1;
this.lockObj2 = lockObj2;
}
@Override
public void run() {
try {
resource(lockObj1, lockObj2);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
public static void resource(String lockA, String lockB) throws InterruptedException {
synchronized (lockA) {
System.out.println(Thread.currentThread().getName() + "\t获取" + lockA);
TimeUnit.SECONDS.sleep(3);
synchronized (lockB) {
System.out.println(Thread.currentThread().getName() + "\t获取" + lockB);
}
}
}
}
实际业务场景应用
public class DistributedLock {
private final Lock localLock = new ReentrantLock();
private final RedisTemplate redisTemplate;
public boolean tryLock(String key, long timeout) {
// 本地锁避免同一JVM内的竞争
if (localLock.tryLock()) {
try {
// Redis分布式锁
String lockValue = UUID.randomUUID().toString();
Boolean result = redisTemplate.opsForValue()
.setIfAbsent(key, lockValue, timeout, TimeUnit.SECONDS);
return Boolean.TRUE.equals(result);
} finally {
localLock.unlock();
}
}
return false;
}
}
public class CacheService {
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final Map<String, Object> cache = new HashMap<>();
private volatile boolean cacheValid = true;
public Object getData(String key) {
// 检查缓存是否有效
if (!cacheValid) {
refreshCache();
}
lock.readLock().lock();
try {
return cache.get(key);
} finally {
lock.readLock().unlock();
}
}
private void refreshCache() {
lock.writeLock().lock();
try {
if (!cacheValid) { // 双重检查
loadDataFromDatabase();
cacheValid = true;
}
} finally {
lock.writeLock().unlock();
}
}
}
public class SecKillService {
private final AtomicInteger stock = new AtomicInteger(100);
private final Semaphore semaphore = new Semaphore(10); // 限制并发数
public boolean secKill(String userId) {
try {
if (semaphore.tryAcquire(100, TimeUnit.MILLISECONDS)) {
try {
// 检查库存
int currentStock = stock.get();
if (currentStock > 0) {
// CAS更新库存
if (stock.compareAndSet(currentStock, currentStock - 1)) {
// 创建订单
createOrder(userId);
return true;
}
}
return false;
} finally {
semaphore.release();
}
}
return false;
} catch (InterruptedException e) {
return false;
}
}
}
小结
| 业务场景 | 推荐方案 | 原因 |
| 简单互斥 | synchronized | 语法简单,JVM优化 |
| 需要超时控制 | ReentrantLock | 支持tryLock |
| 读多写少 | ReadWriteLock | 读操作并发 |
| 计数操作 | AtomicInteger | 无锁高性能 |
| 高并发计数 | LongAdder | 分段减少竞争 |
| 限流控制 | Semaphore | 控制并发数 |
| 等待完成 | CountDownLatch | 一次性同步 |

浙公网安备 33010602011771号