冬月小站

第六章 并发编程

Feb 14, 2025
19
0

一、Java 并发编程基础

1. 线程的创建与管理

Java 中创建线程的三种方式:

(1) 继承 Thread

public class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("Thread running: " + Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start(); // 启动线程
    }
}

(2) 实现 Runnable 接口

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("Runnable running: " + Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable());
        thread.start();
    }
}

(3) 实现 Callable 接口(可返回结果)

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

public class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        return "Callable result: " + Thread.currentThread().getName();
    }

    public static void main(String[] args) throws Exception {
        FutureTask<String> futureTask = new FutureTask<>(new MyCallable());
        Thread thread = new Thread(futureTask);
        thread.start();
        System.out.println(futureTask.get()); // 获取结果
    }
}

2. 线程同步机制

(1) synchronized 关键字

public class SynchronizedExample {
    private int counter = 0;

    // 同步方法
    public synchronized void increment() {
        counter++;
    }

    // 同步代码块
    public void incrementBlock() {
        synchronized (this) {
            counter++;
        }
    }
}

(2) ReentrantLock 显式锁

import java.util.concurrent.locks.ReentrantLock;

public class LockExample {
    private final ReentrantLock lock = new ReentrantLock();
    private int counter = 0;

    public void increment() {
        lock.lock();
        try {
            counter++;
        } finally {
            lock.unlock();
        }
    }
}

二、线程池与 Executor 框架

1. 使用 Executors 创建线程池

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExample {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(4);

        for (int i = 0; i < 10; i++) {
            executor.submit(() -> {
                System.out.println("Task executed by: " + Thread.currentThread().getName());
            });
        }

        executor.shutdown(); // 关闭线程池
    }
}

2. 自定义 ThreadPoolExecutor

import java.util.concurrent.*;

public class CustomThreadPool {
    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
            2,                      // 核心线程数
            5,                      // 最大线程数
            60, TimeUnit.SECONDS,   // 空闲线程存活时间
            new LinkedBlockingQueue<>(10) // 任务队列
        );

        executor.submit(() -> System.out.println("Custom task running"));
        executor.shutdown();
    }
}

三、并发工具类

1. CountDownLatch(等待多个任务完成)

import java.util.concurrent.CountDownLatch;

public class CountDownLatchExample {
    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("Task done");
                latch.countDown();
            }).start();
        }

        latch.await(); // 等待所有任务完成
        System.out.println("All tasks completed");
    }
}

2. CyclicBarrier(线程到达屏障时等待)

java

复制

import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierExample {
    public static void main(String[] args) {
        CyclicBarrier barrier = new CyclicBarrier(3, () -> {
            System.out.println("All threads reached the barrier");
        });

        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                try {
                    System.out.println("Thread waiting at barrier");
                    barrier.await();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

四、常见问题与解决方案

1. 死锁(Deadlock)

public class DeadlockExample {
    private static final Object lockA = new Object();
    private static final Object lockB = new Object();

    public static void main(String[] args) {
        new Thread(() -> {
            synchronized (lockA) {
                try { Thread.sleep(100); } catch (InterruptedException e) {}
                synchronized (lockB) {
                    System.out.println("Thread 1");
                }
            }
        }).start();

        new Thread(() -> {
            synchronized (lockB) {
                synchronized (lockA) {
                    System.out.println("Thread 2");
                }
            }
        }).start();
    }
}

解决方案:按固定顺序获取锁,或使用 tryLock 超时机制。


2. 竞态条件(Race Condition)

public class RaceConditionExample {
    private int count = 0;

    public void increment() {
        count++; // 非原子操作
    }

    public static void main(String[] args) throws InterruptedException {
        RaceConditionExample example = new RaceConditionExample();
        ExecutorService executor = Executors.newFixedThreadPool(10);

        for (int i = 0; i < 1000; i++) {
            executor.submit(example::increment);
        }

        executor.shutdown();
        executor.awaitTermination(1, TimeUnit.MINUTES);
        System.out.println(example.count); // 可能小于 1000
    }
}

解决方案:使用 AtomicInteger 或同步方法。

private AtomicInteger count = new AtomicInteger(0);

public void increment() {
    count.incrementAndGet();
}

五、高级主题

1. CompletableFuture(异步编程)

import java.util.concurrent.CompletableFuture;

public class CompletableFutureExample {
    public static void main(String[] args) {
        CompletableFuture.supplyAsync(() -> "Hello")
            .thenApplyAsync(s -> s + " World")
            .thenAccept(System.out::println); // 输出 "Hello World"
    }
}

2. ConcurrentHashMap(线程安全哈希表)

import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentHashMapExample {
    public static void main(String[] args) {
        ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
        map.put("key1", 1);
        map.computeIfAbsent("key2", k -> 2);
        System.out.println(map.get("key2")); // 输出 2
    }
}

六、最佳实践

  1. 避免过早优化:仅在必要时引入并发。

  2. 优先使用并发工具类:如 ConcurrentHashMapAtomicInteger

  3. 缩小同步范围:减少锁的持有时间。

  4. 使用线程池:避免频繁创建/销毁线程。

  5. 注意资源关闭:如数据库连接、文件句柄。


总结

Java 并发编程的核心在于理解线程安全、锁机制和并发工具类的使用。通过合理使用线程池、原子变量和并发集合类,可以显著提升程序性能并减少风险。推荐深入学习《Java并发编程实战》和 Oracle 官方文档以掌握更多高级技巧。