Java 多线程
1. 多线程基础概念
什么是线程?
- 线程(Thread):程序执行的最小单位,一个历程(如一个 Java 程序)可以包含多个线程。
- 多线程的优势:
- 进步 CPU 利用率(如后台使命与 UI 线程分离)。
- 简化复杂使命的逻辑(如并行处置惩罚)。
单线程 vs 多线程
- 单线程:按顺序执行使命(如逐行执行代码)。
- 多线程:同时执行多个使命(如同时下载多个文件)。
2. 线程的创建与启动
2.1 继承 Thread 类
- public class MyThread extends Thread {
- @Override
- public void run() {
- System.out.println("线程执行:" + Thread.currentThread().getName());
- }
- public static void main(String[] args) {
- MyThread thread = new MyThread();
- thread.start(); // 启动线程(自动调用 run())
- }
- }
复制代码 2.2 实现 Runnable 接口(推荐)
- public class MyRunnable implements Runnable {
- @Override
- public void run() {
- System.out.println("线程执行:" + Thread.currentThread().getName());
- }
- public static void main(String[] args) {
- Thread thread = new Thread(new MyRunnable());
- thread.start();
- }
- }
复制代码 2.3 使用 Callable 和 Future(带返回值)
- import java.util.concurrent.*;
- public class MyCallable implements Callable<Integer> {
- @Override
- public Integer call() throws Exception {
- return 42;
- }
- public static void main(String[] args) throws ExecutionException, InterruptedException {
- ExecutorService executor = Executors.newSingleThreadExecutor();
- Future<Integer> future = executor.submit(new MyCallable());
- System.out.println("结果:" + future.get()); // 阻塞直到获取结果
- executor.shutdown();
- }
- }
复制代码 2.4 Lambda 简化写法
- new Thread(() -> System.out.println("Lambda 线程")).start();
复制代码 3. 线程的生命周期
线程的 6 种状态(通过 Thread.getState() 查看):
状态描述NEW线程已创建但未启动(未调用 start())。RUNNABLE线程正在运行或等候 CPU 调度。BLOCKED线程等候锁(如 synchronized 代码块)。WAITING无穷期等候(如调用 wait())。TIMED_WAITING有限期等候(如调用 sleep(1000))。TERMINATED线程执行完毕或被停止。 4. 线程同步与锁
4.1 synchronized 关键字
- 作用:确保同一时间只有一个线程访问共享资源。
- 使用方式:
- 修饰实例方法:锁是当前实例对象。
- 修饰静态方法:锁是类的 Class 对象。
- 修饰代码块:锁是手动指定的对象。
- public class SyncCounter {
- private int count = 0;
- public synchronized void increment() {
- count++; // 线程安全操作
- }
- public static void main(String[] args) throws InterruptedException {
- SyncCounter counter = new SyncCounter();
- Thread t1 = new Thread(() -> { for (int i=0; i<10000; i++) counter.increment(); });
- Thread t2 = new Thread(() -> { for (int i=0; i<10000; i++) counter.increment(); });
- t1.start(); t2.start(); t1.join(); t2.join();
- System.out.println(counter.count); // 输出 20000
- }
- }
复制代码 4.2 ReentrantLock(可重入锁)
- import java.util.concurrent.locks.*;
- public class LockCounter {
- private int count = 0;
- private final ReentrantLock lock = new ReentrantLock();
- public void increment() {
- lock.lock();
- try {
- count++;
- } finally {
- lock.unlock(); // 确保锁释放
- }
- }
- }
复制代码 5. 线程间通讯
5.1 wait() 和 notify()
- wait():释放锁并进入等候状态。
- notify():叫醒一个等候线程。
- notifyAll():叫醒全部等候线程。
- public class WaitNotifyDemo {
- private static final Object lock = new Object();
- private static boolean isProduced = false;
- public static void main(String[] args) {
- // 生产者
- new Thread(() -> {
- synchronized (lock) {
- System.out.println("生产者:生产了一个产品");
- isProduced = true;
- lock.notify(); // 唤醒消费者
- }
- }).start();
- // 消费者
- new Thread(() -> {
- synchronized (lock) {
- while (!isProduced) {
- try {
- System.out.println("消费者:等待产品...");
- lock.wait(); // 释放锁并等待
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- System.out.println("消费者:消费了产品");
- }
- }).start();
- }
- }
复制代码 5.2 BlockingQueue(壅闭队列)
- import java.util.concurrent.*;
- public class BlockingQueueDemo {
- public static void main(String[] args) {
- BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
- // 生产者
- new Thread(() -> {
- try {
- queue.put(1); // 阻塞直到队列有空位
- System.out.println("生产了 1");
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }).start();
- // 消费者
- new Thread(() -> {
- try {
- Integer item = queue.take(); // 阻塞直到队列有数据
- System.out.println("消费了 " + item);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }).start();
- }
- }
复制代码 6. 线程池
6.1 为什么须要线程池?
- 资源开销:频繁创建和销毁线程本钱高。
- 管理线程:统一管理线程的生命周期和数目。
6.2 使用 Executors 创建线程池
- import java.util.concurrent.*;
- public class ThreadPoolDemo {
- public static void main(String[] args) {
- ExecutorService executor = Executors.newFixedThreadPool(2);
- for (int i=0; i<5; i++) {
- executor.submit(() -> {
- System.out.println("任务由线程执行:" + Thread.currentThread().getName());
- });
- }
- executor.shutdown(); // 关闭线程池
- }
- }
复制代码 6.3 自界说线程池
- ThreadPoolExecutor customPool = new ThreadPoolExecutor(
- 2, // 核心线程数
- 4, // 最大线程数
- 60, // 空闲线程存活时间(秒)
- TimeUnit.SECONDS,
- new ArrayBlockingQueue<>(10), // 任务队列
- new ThreadPoolExecutor.AbortPolicy() // 拒绝策略
- );
复制代码 7. 高级并发工具类
7.1 CountDownLatch(倒计时门闩)
- public class CountDownLatchDemo {
- public static void main(String[] args) throws InterruptedException {
- CountDownLatch latch = new CountDownLatch(3);
- for (int i=0; i<3; i++) {
- new Thread(() -> {
- System.out.println("子线程完成");
- latch.countDown(); // 计数器减 1
- }).start();
- }
- latch.await(); // 等待计数器归零
- System.out.println("所有子线程完成");
- }
- }
复制代码 7.2 CyclicBarrier(循环栅栏)
- public class CyclicBarrierDemo {
- public static void main(String[] args) {
- CyclicBarrier barrier = new CyclicBarrier(3, () ->
- System.out.println("所有线程到达栅栏"));
- for (int i=0; i<3; i++) {
- new Thread(() -> {
- try {
- System.out.println("线程等待");
- barrier.await(); // 等待其他线程
- } catch (Exception e) {
- e.printStackTrace();
- }
- }).start();
- }
- }
- }
复制代码 7.3 Semaphore(信号量)
- public class SemaphoreDemo {
- public static void main(String[] args) {
- Semaphore semaphore = new Semaphore(3); // 允许 3 个线程同时访问
- for (int i=0; i<5; i++) {
- new Thread(() -> {
- try {
- semaphore.acquire(); // 获取许可
- System.out.println("线程进入");
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- } finally {
- semaphore.release(); // 释放许可
- }
- }).start();
- }
- }
- }
复制代码 8. 原子操纵与无锁编程
8.1 原子类(AtomicInteger)
- import java.util.concurrent.atomic.*;
- public class AtomicDemo {
- private AtomicInteger count = new AtomicInteger(0);
- public void increment() {
- count.incrementAndGet(); // 原子操作
- }
- public static void main(String[] args) {
- AtomicDemo demo = new AtomicDemo();
- // 多线程安全操作
- }
- }
复制代码 8.2 LongAdder(高性能计数器)
- import java.util.concurrent.atomic.LongAdder;
- public class LongAdderDemo {
- private LongAdder adder = new LongAdder();
- public void increment() {
- adder.increment();
- }
- public long get() {
- return adder.sum();
- }
- }
复制代码 9. 常见题目与最佳实践
9.1 怎样避免死锁?
- 死锁条件:互斥、持有并等候、不可抢占、循环等候。
- 办理方案:
- 按固定顺序获取锁。
- 使用 tryLock 设置超时时间。
9.2 性能优化发起
- 减少锁的粒度(如使用分段锁)。
- 优先使用无锁数据结构(如 ConcurrentHashMap)。
9.3 ThreadLocal(线程局部变量)
- public class ThreadLocalDemo {
- private static ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 0);
- public static void main(String[] args) {
- new Thread(() -> {
- threadLocal.set(1);
- System.out.println(threadLocal.get()); // 输出 1
- }).start();
- new Thread(() -> {
- System.out.println(threadLocal.get()); // 输出 0
- }).start();
- }
- }
复制代码 10. 总结
总结
- 核心概念:线程、同步、通讯、线程池。
- 关键工具:synchronized、ReentrantLock、BlockingQueue、CountDownLatch。
- 最佳实践:避免死锁、优先使用线程池、利用原子类。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |