Java 多线程

打印 上一主题 下一主题

主题 892|帖子 892|积分 2676

Java 多线程

1. 多线程基础概念

什么是线程?



  • 线程(Thread):程序执行的最小单位,一个历程(如一个 Java 程序)可以包含多个线程。
  • 多线程的优势

    • 进步 CPU 利用率(如后台使命与 UI 线程分离)。
    • 简化复杂使命的逻辑(如并行处置惩罚)。

单线程 vs 多线程



  • 单线程:按顺序执行使命(如逐行执行代码)。
  • 多线程:同时执行多个使命(如同时下载多个文件)。

2. 线程的创建与启动

2.1 继承 Thread 类

  1. public class MyThread extends Thread {
  2.     @Override
  3.     public void run() {
  4.         System.out.println("线程执行:" + Thread.currentThread().getName());
  5.     }
  6.     public static void main(String[] args) {
  7.         MyThread thread = new MyThread();
  8.         thread.start(); // 启动线程(自动调用 run())
  9.     }
  10. }
复制代码
2.2 实现 Runnable 接口(推荐)

  1. public class MyRunnable implements Runnable {
  2.     @Override
  3.     public void run() {
  4.         System.out.println("线程执行:" + Thread.currentThread().getName());
  5.     }
  6.     public static void main(String[] args) {
  7.         Thread thread = new Thread(new MyRunnable());
  8.         thread.start();
  9.     }
  10. }
复制代码
2.3 使用 Callable 和 Future(带返回值)

  1. import java.util.concurrent.*;
  2. public class MyCallable implements Callable<Integer> {
  3.     @Override
  4.     public Integer call() throws Exception {
  5.         return 42;
  6.     }
  7.     public static void main(String[] args) throws ExecutionException, InterruptedException {
  8.         ExecutorService executor = Executors.newSingleThreadExecutor();
  9.         Future<Integer> future = executor.submit(new MyCallable());
  10.         System.out.println("结果:" + future.get()); // 阻塞直到获取结果
  11.         executor.shutdown();
  12.     }
  13. }
复制代码
2.4 Lambda 简化写法

  1. 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 对象。
    • 修饰代码块:锁是手动指定的对象。

  1. public class SyncCounter {
  2.     private int count = 0;
  3.     public synchronized void increment() {
  4.         count++; // 线程安全操作
  5.     }
  6.     public static void main(String[] args) throws InterruptedException {
  7.         SyncCounter counter = new SyncCounter();
  8.         Thread t1 = new Thread(() -> { for (int i=0; i<10000; i++) counter.increment(); });
  9.         Thread t2 = new Thread(() -> { for (int i=0; i<10000; i++) counter.increment(); });
  10.         t1.start(); t2.start(); t1.join(); t2.join();
  11.         System.out.println(counter.count); // 输出 20000
  12.     }
  13. }
复制代码
4.2 ReentrantLock(可重入锁)

  1. import java.util.concurrent.locks.*;
  2. public class LockCounter {
  3.     private int count = 0;
  4.     private final ReentrantLock lock = new ReentrantLock();
  5.     public void increment() {
  6.         lock.lock();
  7.         try {
  8.             count++;
  9.         } finally {
  10.             lock.unlock(); // 确保锁释放
  11.         }
  12.     }
  13. }
复制代码

5. 线程间通讯

5.1 wait() 和 notify()



  • wait():释放锁并进入等候状态。
  • notify():叫醒一个等候线程。
  • notifyAll():叫醒全部等候线程。
  1. public class WaitNotifyDemo {
  2.     private static final Object lock = new Object();
  3.     private static boolean isProduced = false;
  4.     public static void main(String[] args) {
  5.         // 生产者
  6.         new Thread(() -> {
  7.             synchronized (lock) {
  8.                 System.out.println("生产者:生产了一个产品");
  9.                 isProduced = true;
  10.                 lock.notify(); // 唤醒消费者
  11.             }
  12.         }).start();
  13.         // 消费者
  14.         new Thread(() -> {
  15.             synchronized (lock) {
  16.                 while (!isProduced) {
  17.                     try {
  18.                         System.out.println("消费者:等待产品...");
  19.                         lock.wait(); // 释放锁并等待
  20.                     } catch (InterruptedException e) {
  21.                         e.printStackTrace();
  22.                     }
  23.                 }
  24.                 System.out.println("消费者:消费了产品");
  25.             }
  26.         }).start();
  27.     }
  28. }
复制代码
5.2 BlockingQueue(壅闭队列)

  1. import java.util.concurrent.*;
  2. public class BlockingQueueDemo {
  3.     public static void main(String[] args) {
  4.         BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
  5.         // 生产者
  6.         new Thread(() -> {
  7.             try {
  8.                 queue.put(1); // 阻塞直到队列有空位
  9.                 System.out.println("生产了 1");
  10.             } catch (InterruptedException e) {
  11.                 e.printStackTrace();
  12.             }
  13.         }).start();
  14.         // 消费者
  15.         new Thread(() -> {
  16.             try {
  17.                 Integer item = queue.take(); // 阻塞直到队列有数据
  18.                 System.out.println("消费了 " + item);
  19.             } catch (InterruptedException e) {
  20.                 e.printStackTrace();
  21.             }
  22.         }).start();
  23.     }
  24. }
复制代码

6. 线程池

6.1 为什么须要线程池?



  • 资源开销:频繁创建和销毁线程本钱高。
  • 管理线程:统一管理线程的生命周期和数目。
6.2 使用 Executors 创建线程池

  1. import java.util.concurrent.*;
  2. public class ThreadPoolDemo {
  3.     public static void main(String[] args) {
  4.         ExecutorService executor = Executors.newFixedThreadPool(2);
  5.         for (int i=0; i<5; i++) {
  6.             executor.submit(() -> {
  7.                 System.out.println("任务由线程执行:" + Thread.currentThread().getName());
  8.             });
  9.         }
  10.         executor.shutdown(); // 关闭线程池
  11.     }
  12. }
复制代码
6.3 自界说线程池

  1. ThreadPoolExecutor customPool = new ThreadPoolExecutor(
  2.     2, // 核心线程数
  3.     4, // 最大线程数
  4.     60, // 空闲线程存活时间(秒)
  5.     TimeUnit.SECONDS,
  6.     new ArrayBlockingQueue<>(10), // 任务队列
  7.     new ThreadPoolExecutor.AbortPolicy() // 拒绝策略
  8. );
复制代码

7. 高级并发工具类

7.1 CountDownLatch(倒计时门闩)

  1. public class CountDownLatchDemo {
  2.     public static void main(String[] args) throws InterruptedException {
  3.         CountDownLatch latch = new CountDownLatch(3);
  4.         for (int i=0; i<3; i++) {
  5.             new Thread(() -> {
  6.                 System.out.println("子线程完成");
  7.                 latch.countDown(); // 计数器减 1
  8.             }).start();
  9.         }
  10.         latch.await(); // 等待计数器归零
  11.         System.out.println("所有子线程完成");
  12.     }
  13. }
复制代码
7.2 CyclicBarrier(循环栅栏)

  1. public class CyclicBarrierDemo {
  2.     public static void main(String[] args) {
  3.         CyclicBarrier barrier = new CyclicBarrier(3, () ->
  4.             System.out.println("所有线程到达栅栏"));
  5.         for (int i=0; i<3; i++) {
  6.             new Thread(() -> {
  7.                 try {
  8.                     System.out.println("线程等待");
  9.                     barrier.await(); // 等待其他线程
  10.                 } catch (Exception e) {
  11.                     e.printStackTrace();
  12.                 }
  13.             }).start();
  14.         }
  15.     }
  16. }
复制代码
7.3 Semaphore(信号量)

  1. public class SemaphoreDemo {
  2.     public static void main(String[] args) {
  3.         Semaphore semaphore = new Semaphore(3); // 允许 3 个线程同时访问
  4.         for (int i=0; i<5; i++) {
  5.             new Thread(() -> {
  6.                 try {
  7.                     semaphore.acquire(); // 获取许可
  8.                     System.out.println("线程进入");
  9.                     Thread.sleep(1000);
  10.                 } catch (InterruptedException e) {
  11.                     e.printStackTrace();
  12.                 } finally {
  13.                     semaphore.release(); // 释放许可
  14.                 }
  15.             }).start();
  16.         }
  17.     }
  18. }
复制代码

8. 原子操纵与无锁编程

8.1 原子类(AtomicInteger)

  1. import java.util.concurrent.atomic.*;
  2. public class AtomicDemo {
  3.     private AtomicInteger count = new AtomicInteger(0);
  4.     public void increment() {
  5.         count.incrementAndGet(); // 原子操作
  6.     }
  7.     public static void main(String[] args) {
  8.         AtomicDemo demo = new AtomicDemo();
  9.         // 多线程安全操作
  10.     }
  11. }
复制代码
8.2 LongAdder(高性能计数器)

  1. import java.util.concurrent.atomic.LongAdder;
  2. public class LongAdderDemo {
  3.     private LongAdder adder = new LongAdder();
  4.     public void increment() {
  5.         adder.increment();
  6.     }
  7.     public long get() {
  8.         return adder.sum();
  9.     }
  10. }
复制代码

9. 常见题目与最佳实践

9.1 怎样避免死锁?



  • 死锁条件:互斥、持有并等候、不可抢占、循环等候。
  • 办理方案

    • 按固定顺序获取锁。
    • 使用 tryLock 设置超时时间。

9.2 性能优化发起



  • 减少锁的粒度(如使用分段锁)。
  • 优先使用无锁数据结构(如 ConcurrentHashMap)。
9.3 ThreadLocal(线程局部变量)

  1. public class ThreadLocalDemo {
  2.     private static ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 0);
  3.     public static void main(String[] args) {
  4.         new Thread(() -> {
  5.             threadLocal.set(1);
  6.             System.out.println(threadLocal.get()); // 输出 1
  7.         }).start();
  8.         new Thread(() -> {
  9.             System.out.println(threadLocal.get()); // 输出 0
  10.         }).start();
  11.     }
  12. }
复制代码

10. 总结

总结



  • 核心概念:线程、同步、通讯、线程池。
  • 关键工具:synchronized、ReentrantLock、BlockingQueue、CountDownLatch。
  • 最佳实践:避免死锁、优先使用线程池、利用原子类。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

圆咕噜咕噜

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表