DEV Community

Liu yu
Liu yu

Posted on

Java并发简明教程

1. 并发基础

并发是指多个线程同时执行任务的能力。Java通过内置的多线程支持提供了强大的并发编程能力。

1.1 线程与进程

  • 进程:操作系统中运行的程序,拥有独立的内存空间。
  • 线程:进程中的执行单元,共享进程的内存,但有自己的栈。Java线程是轻量级的,适合并发任务。
  • Java中,线程由Thread类或Runnable接口实现。

1.2 创建线程

Java中有以下几种创建线程的方式:

  1. 继承Thread
   class MyThread extends Thread {
       public void run() {
           System.out.println("MyThread running");
       }
   }
   public class Main {
       public static void main(String[] args) {
           MyThread thread = new MyThread();
           thread.start(); // 启动线程
       }
   }
Enter fullscreen mode Exit fullscreen mode
  1. 实现Runnable接口(推荐):
   class MyRunnable implements Runnable {
       public void run() {
           System.out.println("MyRunnable running");
       }
   }
   public class Main {
       public static void main(String[] args) {
           Thread thread = new Thread(new MyRunnable());
           thread.start();
       }
   }
Enter fullscreen mode Exit fullscreen mode
  1. 使用ExecutorService(现代方式,见后续线程池部分)。

1.3 线程状态

Java线程有以下状态:

  • New:线程创建但未启动。
  • Runnable:线程正在运行或等待CPU调度。
  • Blocked:线程等待锁(例如synchronized块)。
  • Waiting:线程等待其他线程的信号(如wait()join())。
  • Timed Waiting:线程在有限时间内等待(如sleep()wait(timeout))。
  • Terminated:线程执行完成或异常终止。

2. 线程安全与同步

多个线程访问共享资源时,可能导致数据不一致或竞争条件。Java提供了多种机制来确保线程安全。

2.1 synchronized关键字

synchronized用于保护共享资源,防止多个线程同时访问。

  • 同步方法
   class Counter {
       private int count = 0;
       public synchronized void increment() {
           count++;
       }
       public int getCount() {
           return count;
       }
   }
Enter fullscreen mode Exit fullscreen mode
  • 同步块(更灵活):
   class Counter {
       private int count = 0;
       private final Object lock = new Object();
       public void increment() {
           synchronized (lock) {
               count++;
           }
       }
   }
Enter fullscreen mode Exit fullscreen mode

2.2 volatile关键字

volatile确保变量的可见性(线程间的内存一致性),但不保证原子性。

class SharedData {
    private volatile boolean flag = false;
    public void setFlag() {
        flag = true;
    }
    public boolean isFlag() {
        return flag;
    }
}
Enter fullscreen mode Exit fullscreen mode
  • 适用场景:适合简单状态标志,不适合复杂操作。

2.3 原子类

java.util.concurrent.atomic包提供原子操作类(如AtomicInteger),无需显式同步。

import java.util.concurrent.atomic.AtomicInteger;
class Counter {
    private AtomicInteger count = new AtomicInteger(0);
    public void increment() {
        count.incrementAndGet();
    }
    public int getCount() {
        return count.get();
    }
}
Enter fullscreen mode Exit fullscreen mode

3. 锁机制(java.util.concurrent.locks)

java.util.concurrent.locks包提供了更灵活的锁机制,优于synchronized

3.1 ReentrantLock

ReentrantLock支持可重入锁,提供更细粒度的控制。

import java.util.concurrent.locks.ReentrantLock;
class Counter {
    private int count = 0;
    private final ReentrantLock lock = new ReentrantLock();
    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock(); // 确保释放锁
        }
    }
}
Enter fullscreen mode Exit fullscreen mode
  • 特性
    • 支持公平锁(new ReentrantLock(true))。
    • 提供tryLock()等高级功能。

3.2 ReadWriteLock

适合读多写少的场景,允许多个线程同时读取,但写操作独占。

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
class SharedData {
    private int data = 0;
    private final ReadWriteLock lock = new ReentrantReadWriteLock();
    public void read() {
        lock.readLock().lock();
        try {
            System.out.println("Read: " + data);
        } finally {
            lock.readLock().unlock();
        }
    }
    public void write(int value) {
        lock.writeLock().lock();
        try {
            data = value;
        } finally {
            lock.writeLock().unlock();
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

4. 线程池与Executor框架

手动创建线程开销大,Java提供了ExecutorService来管理线程池。

4.1 创建线程池

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExample {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(2);
        for (int i = 0; i < 5; i++) {
            executor.submit(() -> System.out.println("Task executed by " + Thread.currentThread().getName()));
        }
        executor.shutdown(); // 关闭线程池
    }
}
Enter fullscreen mode Exit fullscreen mode
  • 常见线程池
    • Executors.newFixedThreadPool(n):固定大小线程池。
    • Executors.newCachedThreadPool():动态大小线程池。
    • Executors.newSingleThreadExecutor():单线程执行。

4.2 Future与异步任务

Future用于获取异步任务的结果。

import java.util.concurrent.*;
public class FutureExample {
    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newFixedThreadPool(1);
        Future<Integer> future = executor.submit(() -> {
            Thread.sleep(1000);
            return 42;
        });
        System.out.println("Result: " + future.get()); // 阻塞等待结果
        executor.shutdown();
    }
}
Enter fullscreen mode Exit fullscreen mode

5. 并发工具类

java.util.concurrent包提供了多种高级并发工具。

5.1 Semaphore(信号量)

控制同时访问资源的线程数量。

import java.util.concurrent.Semaphore;
public class SemaphoreExample {
    private static final Semaphore semaphore = new Semaphore(2); // 允许2个线程并发
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 5; i++) {
            executor.submit(() -> {
                try {
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName() + " acquired");
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    semaphore.release();
                }
            });
        }
        executor.shutdown();
    }
}
Enter fullscreen mode Exit fullscreen mode
  • 注意:Java的Semaphore通常使用阻塞等待(让权等待),而不是忙等待,因为它依赖内核调度。

5.2 CountDownLatch

允许线程等待一组操作完成。

import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(3);
        ExecutorService executor = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 3; i++) {
            executor.submit(() -> {
                System.out.println("Task completed");
                latch.countDown();
            });
        }
        latch.await(); // 等待3个任务完成
        System.out.println("All tasks done");
        executor.shutdown();
    }
}
Enter fullscreen mode Exit fullscreen mode

5.3 CyclicBarrier

让一组线程在某个点同步等待。

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 barrier"));
        ExecutorService executor = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 3; i++) {
            executor.submit(() -> {
                System.out.println(Thread.currentThread().getName() + " reached");
                try {
                    barrier.await();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }
        executor.shutdown();
    }
}
Enter fullscreen mode Exit fullscreen mode

6. 并发集合

java.util.concurrent提供了线程安全的集合类:

  • ConcurrentHashMap:线程安全的哈希表,允许多线程并发读写。
  import java.util.concurrent.ConcurrentHashMap;
  public class ConcurrentMapExample {
      public static void main(String[] args) {
          ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
          map.put("key", 1);
          System.out.println(map.get("key"));
      }
  }
Enter fullscreen mode Exit fullscreen mode
  • CopyOnWriteArrayList:适合读多写少的场景,写操作会复制整个列表。
  • BlockingQueue:线程安全的队列,用于生产者-消费者模式。

java
  import java.util.concurrent.ArrayBlockingQueue;
  import java.util.concurrent.BlockingQueue;
  public class Bloc
Enter fullscreen mode Exit fullscreen mode

Top comments (0)