并发基础:线程与线程池
一核一线程顺序执行很简单;真实世界是:下载、算数、写日志可能同时发生。本周建立并发 最小可用认知,不追求一次吃完 JUC 全家桶。
线程是什么
线程是操作系统调度的最小执行单元。Java 里启动线程的经典写法:
Thread t = new Thread(() -> {
System.out.println("运行在线程: " + Thread.currentThread().getName());
});
t.start(); // 注意是 start,不是 run
run() 只是普通方法调用;start() 才会真正起新线程。
为什么不能无脑 new Thread
线程是昂贵资源。请求一多就新建线程,会把系统打满。正确姿势通常是:线程池。
ExecutorService pool = Executors.newFixedThreadPool(4);
for (int i = 0; i < 10; i++) {
int taskId = i;
pool.submit(() -> System.out.println("task " + taskId + " by " + Thread.currentThread().getName()));
}
pool.shutdown();
最基本的安全问题:共享变量
public class Counter {
private int value = 0;
public synchronized void incr() {
value++;
}
public synchronized int get() {
return value;
}
}
多线程同时 value++ 可能丢更新。synchronized 是入门级锁:同一时刻只允许一个线程进入。
更现代的工具(了解名字即可):AtomicInteger、ReentrantLock、concurrent 包下的并发集合。
小 Demo:模拟批量任务
场景:10 个「下载任务」,用线程池执行,主线程等待结束。
ExecutorService pool = Executors.newFixedThreadPool(3);
List<Future<?>> futures = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
int id = i;
futures.add(pool.submit(() -> {
Thread.sleep(200);
System.out.println("done " + id);
return null;
}));
}
for (Future<?> f : futures) {
f.get();
}
pool.shutdown();
本周练习清单
写在最后
并发是深水区。本周目标不是成为并发专家,而是:看见问题、会用线程池、知道共享数据要保护。
下周是本博客品牌周:YoungGc——我第一次看见 GC。
YoungGc · Eden手记
学习是第一生产力。
如发现有错误欢迎指正,欢迎交流,接受反驳。 -- by不为 :)

浙公网安备 33010602011771号