Java 并发编程代码示例

Java 并发编程的核心是 多线程协作、共享资源同步、线程池管理 等,以下是覆盖核心场景的代码示例,包含注释和场景说明,适合学习和实际参考:

一、基础场景:创建线程(3种常用方式)

1. 继承 Thread 类
// 场景:简单独立任务,无返回值
class MyThread extends Thread {
    @Override
    public void run() {
        // 线程执行逻辑
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + ": " + i);
            try {
                Thread.sleep(100); // 模拟任务耗时
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        MyThread thread1 = new MyThread();
        MyThread thread2 = new MyThread();
        thread1.setName("Thread-1");
        thread2.setName("Thread-2");
        
        thread1.start(); // 启动线程(调用 run() 方法)
        thread2.start();
    }
}
2. 实现 Runnable 接口(推荐,解耦线程与任务)
// 场景:多线程共享同一个任务实例(无返回值)
class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + ": " + i);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        // 共享任务实例
        MyRunnable task = new MyRunnable();
        // 线程池(推荐替代直接 new Thread)
        ExecutorService executor = Executors.newFixedThreadPool(2);
        executor.submit(new Thread(task, "Runnable-1"));
        executor.submit(new Thread(task, "Runnable-2"));
        
        executor.shutdown(); // 关闭线程池(等待任务执行完)
    }
}
3. 实现 Callable 接口(有返回值,支持异常抛出)
// 场景:需要获取线程执行结果(如计算任务)
class MyCallable implements Callable<Integer> {
    private int num;

    public MyCallable(int num) {
        this.num = num;
    }

    // 有返回值,可抛出异常
    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= num; i++) {
            sum += i;
            Thread.sleep(50);
        }
        System.out.println(Thread.currentThread().getName() + " 计算完成");
        return sum;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(2);
        
        // 提交任务,返回 Future 对象(用于获取结果)
        Future<Integer> future1 = executor.submit(new MyCallable(10));
        Future<Integer> future2 = executor.submit(new MyCallable(20));
        
        // 获取结果(阻塞等待线程执行完)
        System.out.println("Callable-1 结果:" + future1.get());
        System.out.println("Callable-2 结果:" + future2.get());
        
        executor.shutdown();
    }
}

二、核心场景:共享资源同步(解决线程安全问题)

1. synchronized 关键字(锁方法/代码块)
// 场景:多线程操作共享变量(如计数器),避免并发修改异常
class Counter {
    private int count = 0;

    // 方式1:锁整个方法
    public synchronized void increment() {
        count++;
    }

    // 方式2:锁代码块(更灵活,锁粒度更小)
    public void decrement() {
        synchronized (this) { // 锁对象(通常是当前实例或类对象)
            count--;
        }
    }

    public int getCount() {
        return count;
    }
}

public class SynchronizedDemo {
    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();
        ExecutorService executor = Executors.newFixedThreadPool(10);

        // 10个线程同时执行 increment,共执行1000次
        for (int i = 0; i < 1000; i++) {
            executor.submit(counter::increment);
        }

        executor.shutdown();
        executor.awaitTermination(1, TimeUnit.SECONDS); // 等待所有线程执行完

        System.out.println("最终计数:" + counter.getCount()); // 正确结果:1000(无同步会小于1000)
    }
}
2. ReentrantLock(可重入锁,比 synchronized 更灵活)
// 场景:需要手动控制锁的获取/释放,支持公平锁、条件变量等
class ReentrantLockCounter {
    private int count = 0;
    // 可重入锁(参数 true 表示公平锁,按线程等待顺序获取锁)
    private final Lock lock = new ReentrantLock(true);

    public void increment() {
        lock.lock(); // 获取锁(未获取到则阻塞)
        try {
            count++; // 临界区(共享资源操作)
        } finally {
            lock.unlock(); // 必须在 finally 中释放锁,避免死锁
        }
    }

    public int getCount() {
        return count;
    }
}

public class ReentrantLockDemo {
    public static void main(String[] args) throws InterruptedException {
        ReentrantLockCounter counter = new ReentrantLockCounter();
        ExecutorService executor = Executors.newFixedThreadPool(10);

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

        executor.shutdown();
        executor.awaitTermination(1, TimeUnit.SECONDS);

        System.out.println("最终计数:" + counter.getCount()); // 1000
    }
}
3. 原子类(无锁同步,基于 CAS 机制)
// 场景:简单的数值增减,无需锁,性能更高
public class AtomicDemo {
    public static void main(String[] args) throws InterruptedException {
        // 原子整数(线程安全的自增/自减)
        AtomicInteger atomicCount = new AtomicInteger(0);
        ExecutorService executor = Executors.newFixedThreadPool(10);

        for (int i = 0; i < 1000; i++) {
            // incrementAndGet():原子自增并返回新值
            executor.submit(atomicCount::incrementAndGet);
        }

        executor.shutdown();
        executor.awaitTermination(1, TimeUnit.SECONDS);

        System.out.println("最终计数:" + atomicCount.get()); // 1000
    }
}

三、高级场景:线程协作(等待/通知机制)

1. Condition 条件变量(配合 ReentrantLock)
// 场景:生产者-消费者模型(线程间协作,避免忙等)
class MessageQueue {
    private final Queue<String> queue = new LinkedList<>();
    private final Lock lock = new ReentrantLock();
    // 条件变量:队列非空(消费者等待)、队列未满(生产者等待)
    private final Condition notEmpty = lock.newCondition();
    private final Condition notFull = lock.newCondition();
    private final int capacity = 5; // 队列最大容量

    // 生产者放入消息
    public void put(String message) throws InterruptedException {
        lock.lock();
        try {
            // 队列满了,生产者等待
            while (queue.size() == capacity) {
                notFull.await(); // 释放锁,进入等待队列
            }
            queue.offer(message);
            System.out.println("生产者放入:" + message);
            notEmpty.signal(); // 通知消费者:队列非空了
        } finally {
            lock.unlock();
        }
    }

    // 消费者取出消息
    public String take() throws InterruptedException {
        lock.lock();
        try {
            // 队列为空,消费者等待
            while (queue.isEmpty()) {
                notEmpty.await();
            }
            String message = queue.poll();
            System.out.println("消费者取出:" + message);
            notFull.signal(); // 通知生产者:队列未满了
            return message;
        } finally {
            lock.unlock();
        }
    }
}

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

        // 2个生产者
        executor.submit(() -> {
            try {
                queue.put("消息1");
                queue.put("消息2");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        executor.submit(() -> {
            try {
                queue.put("消息3");
                queue.put("消息4");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        // 2个消费者
        executor.submit(() -> {
            try {
                queue.take();
                queue.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        executor.submit(() -> {
            try {
                queue.take();
                queue.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        executor.shutdown();
    }
}
2. CountDownLatch(线程等待多任务完成)
// 场景:主线程等待所有子线程执行完再继续(如并行计算汇总结果)
public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        int threadNum = 3;
        // 计数器初始值 = 线程数
        CountDownLatch latch = new CountDownLatch(threadNum);

        ExecutorService executor = Executors.newFixedThreadPool(threadNum);
        for (int i = 0; i < threadNum; i++) {
            int taskId = i;
            executor.submit(() -> {
                try {
                    System.out.println("任务" + taskId + "执行中...");
                    Thread.sleep(1000);
                    System.out.println("任务" + taskId + "执行完成");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    latch.countDown(); // 计数器减1
                }
            });
        }

        System.out.println("主线程等待所有任务完成...");
        latch.await(); // 主线程阻塞,直到计数器为0
        System.out.println("所有任务完成,主线程继续执行");

        executor.shutdown();
    }
}

四、线程池(推荐:控制线程数量,避免资源耗尽)

Java 推荐用 ThreadPoolExecutor 自定义线程池(避免 Executors 工具类的默认缺陷):

public class ThreadPoolDemo {
    public static void main(String[] args) {
        // 核心参数说明:
        // 1. 核心线程数(常驻线程):2
        // 2. 最大线程数:5
        // 3. 空闲线程存活时间:60秒(超过核心线程数的线程,空闲60秒后销毁)
        // 4. 时间单位:秒
        // 5. 任务队列(阻塞队列):容量10(超出核心线程数的任务先入队)
        // 6. 线程工厂(创建线程的方式):默认
        // 7. 拒绝策略(队列满+最大线程数满时,如何处理新任务):抛异常
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2,
                5,
                60,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(10),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );

        // 提交15个任务(核心2 + 队列10 + 最大3 = 15,刚好不触发拒绝策略)
        for (int i = 0; i < 15; i++) {
            int taskId = i;
            executor.submit(() -> {
                System.out.println("线程" + Thread.currentThread().getId() + "执行任务" + taskId);
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }

        executor.shutdown(); // 平缓关闭:等待已提交的任务执行完,不再接收新任务
        // executor.shutdownNow(); // 强制关闭:立即中断正在执行的任务,返回未执行的任务
    }
}

关键说明:

  1. 线程安全:共享资源必须通过 synchronizedLock、原子类等方式同步,否则会出现 ConcurrentModificationException 或数据不一致;
  2. 线程池:避免直接 new Thread(),线程池可复用线程、控制并发数,降低资源开销;
  3. 协作机制ConditionCountDownLatchCyclicBarrier 等工具类可实现复杂的线程协作,比 wait()/notify() 更灵活;
  4. 异常处理:线程中未捕获的异常会导致线程终止,建议在 run()/call() 中统一捕获异常。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值