并发编程
1. 并发基础
(1) 进程与线程
进程 :操作系统分配资源的基本单位,每个进程都有独立的内存空间。
线程 :进程中的一条执行路径,是 CPU 调度的基本单位,线程共享进程的资源。
(2) 并发与并行
并发(Concurrency) :多个任务在同一时间段内交替执行。
并行(Parallelism) :多个任务在同一时刻同时执行(通常需要多核 CPU 支持)。
2. 创建线程的方式
在 Java 中,可以通过以下方式创建线程:
(1) 继承 Thread 类
通过继承 Thread 类并重写 run() 方法来定义线程任务。
1 2 3 4 5 6 7 8 9 10 11 12 13 class MyThread extends Thread { @Override public void run () { System.out.println("Thread is running" ); } } public class Main { public static void main (String[] args) { MyThread thread = new MyThread(); thread.start(); } }
(2) 实现 Runnable 接口
通过实现 Runnable 接口并传递给 Thread 对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 class MyRunnable implements Runnable { @Override public void run () { System.out.println("Runnable is running" ); } } public class Main { public static void main (String[] args) { Thread thread = new Thread(new MyRunnable()); thread.start(); } }
(3) 使用 Lambda 表达式
从 Java 8 开始,可以使用 Lambda 表达式简化 Runnable 的实现。
1 2 3 4 5 6 public class Main { public static void main (String[] args) { Thread thread = new Thread(() -> System.out.println("Lambda thread is running" )); thread.start(); } }
(4) 使用 Callable 和 Future
Callable 类似于 Runnable,但它可以返回结果并抛出异常。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util.concurrent.FutureTask;class MyCallable implements Callable <Integer > { @Override public Integer call () throws Exception { return 123 ; } } public class Main { public static void main (String[] args) throws ExecutionException, InterruptedException { FutureTask<Integer> futureTask = new FutureTask<>(new MyCallable()); Thread thread = new Thread(futureTask); thread.start(); System.out.println("Result: " + futureTask.get()); } }
3. 线程的状态
线程在其生命周期中有以下几个状态:
新建(New) :线程对象被创建但尚未启动。
就绪(Runnable) :线程已启动,等待 CPU 调度。
运行(Running) :线程正在执行。
阻塞(Blocked) :线程因某些原因暂停运行。
等待(Waiting) :线程进入无限期等待状态,直到其他线程唤醒。
终止(Terminated) :线程执行完毕或因异常终止。
4. 线程同步
当多个线程访问共享资源时,可能会出现数据不一致的问题。Java 提供了多种线程同步机制来解决这些问题。
(1) synchronized 关键字
synchronized 可以修饰方法或代码块,确保同一时间只有一个线程可以访问。
1 2 3 4 5 6 7 8 9 10 11 class Counter { private int count = 0 ; public synchronized void increment () { count++; } public synchronized int getCount () { return count; } }
(2) Lock 接口
Lock 是一种更灵活的锁机制,提供了比 synchronized 更强大的功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;class Counter { private int count = 0 ; private final Lock lock = new ReentrantLock(); public void increment () { lock.lock(); try { count++; } finally { lock.unlock(); } } public int getCount () { return count; } }
5. 线程间通信
线程之间可以通过以下方式通信:
(1) wait() 和 notify()
wait() 和 notify() 是 Object 类中的方法,用于线程间的协作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class SharedResource { private boolean available = false ; public synchronized void produce () throws InterruptedException { while (available) { wait(); } System.out.println("Producing..." ); available = true ; notify(); } public synchronized void consume () throws InterruptedException { while (!available) { wait(); } System.out.println("Consuming..." ); available = false ; notify(); } }
(2) BlockingQueue
BlockingQueue 是一个线程安全的队列,支持生产者-消费者模式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.BlockingQueue;public class Main { public static void main (String[] args) { BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10 ); Thread producer = new Thread(() -> { try { for (int i = 0 ; i < 10 ; i++) { queue.put(i); System.out.println("Produced: " + i); } } catch (InterruptedException e) { e.printStackTrace(); } }); Thread consumer = new Thread(() -> { try { for (int i = 0 ; i < 10 ; i++) { int value = queue.take(); System.out.println("Consumed: " + value); } } catch (InterruptedException e) { e.printStackTrace(); } }); producer.start(); consumer.start(); } }
7. 并发问题与解决方案
(1) 死锁
多个线程互相等待对方释放锁,导致程序无法继续运行。
(2) 竞态条件
多个线程对共享资源的操作顺序不确定,导致结果不一致。
解决方案 :使用同步机制(如 synchronized 或 Lock)。
(3) 线程饥饿
某些线程长时间得不到 CPU 时间片。
If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. If the images used in the blog infringe your copyright, please contact the author to delete them. Thank you !