第493集多线程 | 字数总计: 4.5k | 阅读时长: 21分钟 | 阅读量:
多线程 1. 概述 1.1 多线程的重要性 多线程 是现代编程的核心技术之一,能够充分利用多核CPU,提高程序执行效率,实现并发处理。
本文内容 :
线程基础 :线程概念和生命周期
线程创建 :创建线程的多种方式
线程同步 :synchronized、Lock等同步机制
线程通信 :wait/notify、Condition等通信机制
线程池 :线程池的使用和原理
并发工具 :CountDownLatch、CyclicBarrier等工具
线程安全 :线程安全问题和解决方案
死锁问题 :死锁的产生和避免
1.2 本文内容结构 本文将从以下几个方面深入探讨多线程:
线程基础 :线程概念和生命周期
线程创建 :创建线程的方式
线程同步 :同步机制和锁
线程通信 :线程间通信方式
线程池 :线程池的使用和原理
并发工具 :并发工具类的使用
线程安全 :线程安全问题解决
死锁问题 :死锁的产生和避免
2. 线程基础 2.1 线程概念 2.1.1 进程和线程 进程 :操作系统资源分配的基本单位,每个进程有独立的内存空间。
线程 :CPU调度的基本单位,同一进程内的线程共享内存空间。
进程 vs 线程 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 进程: ┌─────────────────────────┐ │ 进程1(独立内存空间) │ │ ┌──────┐ ┌──────┐ │ │ │线程1 │ │线程2 │ │ │ └──────┘ └──────┘ │ └─────────────────────────┘ 线程: ┌─────────────────────────┐ │ 共享内存空间 │ │ ┌──────┐ ┌──────┐ │ │ │线程1 │ │线程2 │ │ │ └──────┘ └──────┘ │ └─────────────────────────┘
多线程优势 :
提高CPU利用率 :充分利用多核CPU
提高响应速度 :避免阻塞,提高用户体验
资源利用 :共享内存,节省资源
2.2 线程生命周期 2.2.1 线程状态 线程状态 :
NEW(新建) :线程创建,未启动
RUNNABLE(可运行) :线程可执行
BLOCKED(阻塞) :等待获取锁
WAITING(等待) :无限期等待
TIMED_WAITING(超时等待) :有限期等待
TERMINATED(终止) :线程执行完毕
线程状态转换 :
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 public class ThreadStateExample { public void threadStates () { Thread thread = new Thread (() -> { try { Thread.sleep(1000 ); } catch (InterruptedException e) { e.printStackTrace(); } }); System.out.println(thread.getState()); thread.start(); System.out.println(thread.getState()); try { Thread.sleep(100 ); System.out.println(thread.getState()); } catch (InterruptedException e) { e.printStackTrace(); } try { thread.join(); System.out.println(thread.getState()); } catch (InterruptedException e) { e.printStackTrace(); } } }
3. 线程创建 3.1 继承Thread类 3.1.1 创建线程方式1 继承Thread类 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class ThreadExample1 extends Thread { @Override public void run () { System.out.println("Thread running: " + Thread.currentThread().getName()); for (int i = 0 ; i < 5 ; i++) { System.out.println("Count: " + i); try { Thread.sleep(1000 ); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main (String[] args) { ThreadExample1 thread = new ThreadExample1 (); thread.start(); } }
注意 :
调用start()方法启动线程,会创建新线程执行run()方法
直接调用run()方法不会创建新线程,只是普通方法调用
3.2 实现Runnable接口 3.2.1 创建线程方式2 实现Runnable接口 (推荐):
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 public class ThreadExample2 implements Runnable { @Override public void run () { System.out.println("Thread running: " + Thread.currentThread().getName()); for (int i = 0 ; i < 5 ; i++) { System.out.println("Count: " + i); try { Thread.sleep(1000 ); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main (String[] args) { ThreadExample2 runnable = new ThreadExample2 (); Thread thread = new Thread (runnable); thread.start(); Thread thread2 = new Thread (() -> { System.out.println("Lambda thread running" ); }); thread2.start(); } }
优势 :
3.3 实现Callable接口 3.3.1 创建线程方式3 实现Callable接口 (有返回值):
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 import java.util.concurrent.*;public class ThreadExample3 implements Callable <String> { @Override public String call () throws Exception { System.out.println("Callable thread running" ); Thread.sleep(2000 ); return "Callable result: " + Thread.currentThread().getName(); } public static void main (String[] args) throws Exception { Callable<String> callable = new ThreadExample3 (); FutureTask<String> futureTask = new FutureTask <>(callable); Thread thread = new Thread (futureTask); thread.start(); String result = futureTask.get(); System.out.println("Result: " + result); ExecutorService executor = Executors.newSingleThreadExecutor(); Future<String> future = executor.submit(callable); String result2 = future.get(); System.out.println("Result2: " + result2); executor.shutdown(); } }
Callable vs Runnable :
Callable有返回值,Runnable无返回值
Callable可以抛出异常,Runnable不能
Callable配合Future使用
3.4 线程池创建 3.4.1 创建线程方式4 使用线程池 (推荐):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.util.concurrent.*;public class ThreadPoolExample { public static void main (String[] args) { ExecutorService executor = Executors.newFixedThreadPool(5 ); for (int i = 0 ; i < 10 ; i++) { final int taskId = i; executor.submit(() -> { System.out.println("Task " + taskId + " running in " + Thread.currentThread().getName()); }); } executor.shutdown(); } }
4. 线程同步 4.1 synchronized关键字 4.1.1 synchronized用法 synchronized :Java内置的同步机制,保证同一时刻只有一个线程执行同步代码。
synchronized用法 :
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 public class SynchronizedExample { private int count = 0 ; private final Object lock = new Object (); public synchronized void increment1 () { count++; } public static synchronized void increment2 () { } public void increment3 () { synchronized (this ) { count++; } } public void increment4 () { synchronized (lock) { count++; } } }
synchronized原理 :
1 2 3 4 5 6 7 8 9 10 11 12 public class SynchronizedPrinciple { public synchronized void method1 () { } public void method2 () { synchronized (this ) { } } }
字节码层面 :
synchronized方法:方法标志位ACC_SYNCHRONIZED
synchronized代码块:monitorenter和monitorexit指令
4.2 Lock接口 4.2.1 ReentrantLock ReentrantLock :可重入锁,功能比synchronized更强大。
ReentrantLock使用 :
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 34 35 36 37 38 39 import java.util.concurrent.locks.ReentrantLock;public class LockExample { private int count = 0 ; private final ReentrantLock lock = new ReentrantLock (); public void increment () { lock.lock(); try { count++; } finally { lock.unlock(); } } public void tryLockExample () { if (lock.tryLock()) { try { count++; } finally { lock.unlock(); } } else { System.out.println("Failed to acquire lock" ); } } public void interruptibleLock () throws InterruptedException { lock.lockInterruptibly(); try { count++; } finally { lock.unlock(); } } }
ReentrantLock vs synchronized :
特性
synchronized
ReentrantLock
自动释放
是
否(需手动)
可中断
否
是
公平锁
否
是(可配置)
条件变量
否
是
性能
Java 6后优化,性能相当
性能相当
4.3 ReadWriteLock 4.3.1 读写锁 ReadWriteLock :读写分离锁,提高并发性能。
读写锁使用 :
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 import java.util.concurrent.locks.ReadWriteLock;import java.util.concurrent.locks.ReentrantReadWriteLock;public class ReadWriteLockExample { private int data = 0 ; private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock (); public int read () { readWriteLock.readLock().lock(); try { return data; } finally { readWriteLock.readLock().unlock(); } } public void write (int value) { readWriteLock.writeLock().lock(); try { data = value; } finally { readWriteLock.writeLock().unlock(); } } }
读写锁特点 :
多个读线程可以同时获取读锁
写线程独占写锁,与其他线程互斥
适合读多写少的场景
4.4 volatile关键字 4.4.1 volatile的作用 volatile :保证变量的可见性和有序性,不保证原子性。
volatile使用 :
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 public class VolatileExample { private volatile boolean flag = false ; public void writer () { flag = true ; } public void reader () { while (!flag) { } System.out.println("Flag is true" ); } private volatile int count = 0 ; public void increment () { count++; } private final AtomicInteger atomicCount = new AtomicInteger (0 ); public void atomicIncrement () { atomicCount.incrementAndGet(); } }
volatile原理 :
5. 线程通信 5.1 wait/notify 5.1.1 等待通知机制 wait/notify :Object类的方法,实现线程间通信。
wait/notify使用 :
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 public class WaitNotifyExample { private final Object lock = new Object (); private boolean condition = false ; public void waitThread () throws InterruptedException { synchronized (lock) { while (!condition) { System.out.println("Waiting..." ); lock.wait(); } System.out.println("Condition is true, continue..." ); } } public void notifyThread () { synchronized (lock) { condition = true ; lock.notify(); } } }
wait/notify注意事项 :
必须在synchronized代码块中使用
调用wait()会释放锁
notify()随机唤醒一个线程
notifyAll()唤醒所有等待的线程
5.2 Condition 5.2.1 条件变量 Condition :Lock接口的条件变量,功能类似wait/notify。
Condition使用 :
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.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class ConditionExample { private final Lock lock = new ReentrantLock (); private final Condition condition = lock.newCondition(); private boolean flag = false ; public void await () throws InterruptedException { lock.lock(); try { while (!flag) { condition.await(); } System.out.println("Condition is true" ); } finally { lock.unlock(); } } public void signal () { lock.lock(); try { flag = true ; condition.signal(); } finally { lock.unlock(); } } }
Condition优势 :
可以创建多个Condition
更灵活的线程通信
支持公平锁
5.3 生产者消费者 5.3.1 经典案例 生产者消费者模式 :
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 34 35 36 import java.util.LinkedList;import java.util.Queue;public class ProducerConsumerExample { private final Queue<Integer> queue = new LinkedList <>(); private final int CAPACITY = 10 ; private final Object lock = new Object (); public void produce (int value) throws InterruptedException { synchronized (lock) { while (queue.size() == CAPACITY) { System.out.println("Queue is full, waiting..." ); lock.wait(); } queue.offer(value); System.out.println("Produced: " + value); lock.notifyAll(); } } public int consume () throws InterruptedException { synchronized (lock) { while (queue.isEmpty()) { System.out.println("Queue is empty, waiting..." ); lock.wait(); } int value = queue.poll(); System.out.println("Consumed: " + value); lock.notifyAll(); return value; } } }
6. 线程池 6.1 线程池原理 6.1.1 为什么使用线程池 线程池优势 :
降低资源消耗 :复用线程,减少创建和销毁开销
提高响应速度 :任务到达时,线程已存在
提高线程管理 :统一管理线程,控制并发数
线程池核心参数 :
1 2 3 4 5 6 7 8 9 10 11 public class ThreadPoolCoreParams { }
6.2 线程池创建 6.2.1 Executors工具类 Executors工具类 :
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 import java.util.concurrent.*;public class ExecutorsExample { public void executorsExample () { ExecutorService fixedPool = Executors.newFixedThreadPool(10 ); ExecutorService singlePool = Executors.newSingleThreadExecutor(); ExecutorService cachedPool = Executors.newCachedThreadPool(); ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(5 ); fixedPool.submit(() -> { System.out.println("Task running" ); }); fixedPool.shutdown(); } }
注意 :Executors创建的线程池可能有问题,建议使用ThreadPoolExecutor。
6.3 自定义线程池 6.3.1 ThreadPoolExecutor 自定义线程池 :
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 34 35 36 37 38 39 40 41 42 import java.util.concurrent.*;public class CustomThreadPool { public void customThreadPool () { ThreadPoolExecutor executor = new ThreadPoolExecutor ( 5 , 10 , 60L , TimeUnit.SECONDS, new LinkedBlockingQueue <>(100 ), new ThreadFactory () { @Override public Thread newThread (Runnable r) { Thread thread = new Thread (r); thread.setName("CustomThread-" + thread.getId()); thread.setDaemon(false ); return thread; } }, new ThreadPoolExecutor .CallerRunsPolicy() ); for (int i = 0 ; i < 20 ; i++) { final int taskId = i; executor.submit(() -> { System.out.println("Task " + taskId + " running" ); }); } executor.shutdown(); try { if (!executor.awaitTermination(60 , TimeUnit.SECONDS)) { executor.shutdownNow(); } } catch (InterruptedException e) { executor.shutdownNow(); } } }
6.4 拒绝策略 6.4.1 四种拒绝策略 拒绝策略 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class RejectionPolicy { RejectedExecutionHandler abortPolicy = new ThreadPoolExecutor .AbortPolicy(); RejectedExecutionHandler callerRunsPolicy = new ThreadPoolExecutor .CallerRunsPolicy(); RejectedExecutionHandler discardPolicy = new ThreadPoolExecutor .DiscardPolicy(); RejectedExecutionHandler discardOldestPolicy = new ThreadPoolExecutor .DiscardOldestPolicy(); }
7. 并发工具类 7.1 CountDownLatch 7.1.1 倒计时门闩 CountDownLatch :等待多个线程完成。
CountDownLatch使用 :
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 import java.util.concurrent.CountDownLatch;public class CountDownLatchExample { public void countDownLatchExample () throws InterruptedException { int threadCount = 5 ; CountDownLatch latch = new CountDownLatch (threadCount); for (int i = 0 ; i < threadCount; i++) { final int taskId = i; new Thread (() -> { try { System.out.println("Task " + taskId + " running" ); Thread.sleep(1000 ); latch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); } latch.await(); System.out.println("All tasks completed" ); } }
7.2 CyclicBarrier 7.2.1 循环栅栏 CyclicBarrier :多个线程互相等待。
CyclicBarrier使用 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import java.util.concurrent.CyclicBarrier;public class CyclicBarrierExample { public void cyclicBarrierExample () { int threadCount = 3 ; CyclicBarrier barrier = new CyclicBarrier (threadCount, () -> { System.out.println("All threads reached barrier" ); }); for (int i = 0 ; i < threadCount; i++) { final int threadId = i; new Thread (() -> { try { System.out.println("Thread " + threadId + " waiting at barrier" ); barrier.await(); System.out.println("Thread " + threadId + " passed barrier" ); } catch (Exception e) { e.printStackTrace(); } }).start(); } } }
7.3 Semaphore 7.3.1 信号量 Semaphore :控制并发数量。
Semaphore使用 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import java.util.concurrent.Semaphore;public class SemaphoreExample { public void semaphoreExample () { int permits = 3 ; Semaphore semaphore = new Semaphore (permits ); for (int i = 0 ; i < 10 ; i++) { final int taskId = i; new Thread (() -> { try { semaphore.acquire(); System.out.println("Task " + taskId + " running" ); Thread.sleep(1000 ); semaphore.release(); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); } } }
7.4 CompletableFuture 7.4.1 异步编程 CompletableFuture :异步编程工具。
CompletableFuture使用 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import java.util.concurrent.CompletableFuture;public class CompletableFutureExample { public void completableFutureExample () { CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { return "Hello" ; }).thenApply(s -> s + " World" ) .thenApply(String::toUpperCase); future.thenAccept(result -> { System.out.println("Result: " + result); }); CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello" ); CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "World" ); CompletableFuture<String> combined = future1.thenCombine(future2, (s1, s2) -> s1 + " " + s2); combined.thenAccept(System.out::println); } }
8. 线程安全 8.1 线程安全问题 8.1.1 问题示例 线程安全问题 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class ThreadSafetyProblem { private int count = 0 ; public void increment () { count++; } public synchronized void incrementSync () { count++; } private final AtomicInteger atomicCount = new AtomicInteger (0 ); public void incrementAtomic () { atomicCount.incrementAndGet(); } }
8.2 原子类 8.2.1 Atomic类 原子类 :保证操作的原子性。
原子类使用 :
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 import java.util.concurrent.atomic.*;public class AtomicExample { private final AtomicInteger atomicInt = new AtomicInteger (0 ); public void atomicIntExample () { atomicInt.incrementAndGet(); atomicInt.getAndIncrement(); atomicInt.compareAndSet(0 , 10 ); } private final AtomicLong atomicLong = new AtomicLong (0 ); private final AtomicReference<String> atomicRef = new AtomicReference <>("initial" ); public void atomicRefExample () { atomicRef.compareAndSet("initial" , "updated" ); } private final AtomicIntegerArray atomicArray = new AtomicIntegerArray (10 ); public void atomicArrayExample () { atomicArray.set(0 , 10 ); atomicArray.compareAndSet(0 , 10 , 20 ); } }
8.3 线程安全集合 8.3.1 并发集合 线程安全集合 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.concurrent.*;public class ConcurrentCollectionExample { private final ConcurrentHashMap<String, String> concurrentMap = new ConcurrentHashMap <>(); private final CopyOnWriteArrayList<String> copyOnWriteList = new CopyOnWriteArrayList <>(); private final BlockingQueue<String> blockingQueue = new LinkedBlockingQueue <>(); public void blockingQueueExample () throws InterruptedException { blockingQueue.put("item" ); String item = blockingQueue.take(); } }
9. 死锁问题 9.1 死锁产生 9.1.1 死锁条件 死锁产生的四个必要条件 :
互斥条件 :资源不能被多个线程共享
请求与保持 :线程持有资源并请求新资源
不可剥夺 :资源不能被强制释放
循环等待 :形成循环等待链
死锁示例 :
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 34 35 36 37 38 39 public class DeadlockExample { private final Object lock1 = new Object (); private final Object lock2 = new Object (); public void method1 () { synchronized (lock1) { System.out.println("Method1 acquired lock1" ); try { Thread.sleep(100 ); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lock2) { System.out.println("Method1 acquired lock2" ); } } } public void method2 () { synchronized (lock2) { System.out.println("Method2 acquired lock2" ); try { Thread.sleep(100 ); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lock1) { System.out.println("Method2 acquired lock1" ); } } } public void deadlockTest () { new Thread (this ::method1).start(); new Thread (this ::method2).start(); } }
9.2 死锁避免 9.2.1 避免死锁的方法 避免死锁的方法 :
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 public class DeadlockAvoidance { private final Object lock1 = new Object (); private final Object lock2 = new Object (); public void method1 () { synchronized (lock1) { synchronized (lock2) { } } } public void method2 () { synchronized (lock1) { synchronized (lock2) { } } } public void method3 () { ReentrantLock lock1 = new ReentrantLock (); ReentrantLock lock2 = new ReentrantLock (); while (true ) { if (lock1.tryLock()) { try { if (lock2.tryLock()) { try { return ; } finally { lock2.unlock(); } } } finally { lock1.unlock(); } } try { Thread.sleep(10 ); } catch (InterruptedException e) { e.printStackTrace(); } } } }
9.3 死锁检测 9.3.1 检测死锁 检测死锁 :
1 2 3 4 5 6 7 8 9 10 11 12 jstack <pid> Found one Java-level deadlock: ============================= "Thread-1" : waiting to lock monitor 0x00007f8b1c0001e8 (object 0x000000076ab622a0, a java.lang.Object), which is held by "Thread-0" "Thread-0" : waiting to lock monitor 0x00007f8b1c0002b8 (object 0x000000076ab622b0, a java.lang.Object), which is held by "Thread-1"
10. 实战案例 10.1 线程安全的单例 10.1.1 双重检查锁定 线程安全的单例 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class ThreadSafeSingleton { private static volatile ThreadSafeSingleton instance; private ThreadSafeSingleton () {} public static ThreadSafeSingleton getInstance () { if (instance == null ) { synchronized (ThreadSafeSingleton.class) { if (instance == null ) { instance = new ThreadSafeSingleton (); } } } return instance; } }
10.2 线程池实战 10.2.1 自定义线程池 自定义线程池实战 :
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 public class ThreadPoolPractice { public void customThreadPool () { ThreadPoolExecutor executor = new ThreadPoolExecutor ( 5 , 10 , 60L , TimeUnit.SECONDS, new LinkedBlockingQueue <>(100 ), new ThreadFactory () { private int count = 0 ; @Override public Thread newThread (Runnable r) { Thread thread = new Thread (r); thread.setName("Worker-" + (++count)); return thread; } }, new ThreadPoolExecutor .CallerRunsPolicy() ); for (int i = 0 ; i < 100 ; i++) { final int taskId = i; executor.submit(() -> { System.out.println("Task " + taskId + " running in " + Thread.currentThread().getName()); }); } executor.shutdown(); } }
11. 总结 11.1 核心要点
线程创建 :继承Thread、实现Runnable/Callable、使用线程池
线程同步 :synchronized、Lock、volatile
线程通信 :wait/notify、Condition
线程池 :合理使用线程池,避免频繁创建线程
线程安全 :使用原子类、并发集合
死锁避免 :按顺序获取锁、使用tryLock
11.2 关键理解
synchronized和Lock :功能类似,Lock更灵活
volatile :保证可见性,不保证原子性
线程池 :复用线程,提高性能
并发工具 :简化并发编程
11.3 最佳实践
优先使用线程池 :避免手动创建线程
合理使用锁 :减少锁的粒度,避免死锁
使用并发集合 :线程安全的集合类
避免共享可变状态 :使用不可变对象
相关文章 :