Java 开发大纲
目录
集合
非线程安全集合
List
: 有序集合- ArrayList
- 数据结构:
基于泛型数组
- 特点:查询速度快,增删速度慢
- 数据结构:
- LinkedList
- 数据结构:
基于链表结构
- 特点:查询速度慢,增删速度快
- 数据结构:
- ArrayList
Map
: 将键映射到值的双列集合- HashMap
- 数据结构:
基于哈希表
- 特点:存取无序
- 源码
DEFAULT_INITIAL_CAPACITY
默认为 16MAXIMUM_CAPACITY
默认为 2 的 30 次幂DEFAULT_LOAD_FACTOR
默认负载因子 0.75- 每次会扩容长度为以前的2倍
- 数据结构:
- TreeMap
- 有序
- 数据结构 ->
基于红黑树
- LinkedHashMap
- 数据结构:
基于链表和哈希表
- 特点:存取有序
- 数据结构:
- EnumMap:
- 特点:枚举类型作为键值的Map
- IdentityHashMap:
- 特点:使用 “==” 来比较引用
- WeakHashMap:
- 特点:将键存储在 WeakReference 中
- 场景:用于数据缓存中
- HashMap
Set
: 不能包含重复元素的集合- HashSet:
- 数据结构:
基于哈希表
- 特点:存取无序
- 数据结构:
- TreeSet
- 数据结构:
基于二叉树
- 特点:排序
- 数据结构:
- LinkedHashSet
- 数据结构:
基于链表和哈希表
- 特点:存取有序
- 数据结构:
- EnumSet:
- 特点:值为枚举类型的Set
- BitSet
- HashSet:
Queue/Deque
: 队列- ArrayDeque
- 特点:基于有首尾指针的数组(环形缓冲区)
- PriorityQueue
- 特点:基于优先级的队列
- ArrayDeque
线程安全集合
List
- CopyOnWriteArrayList
- 特点:避免了多线程操作的线程安全问题
- 原理:先复制,再操作,最后替换
- 场景:用在遍历操作比更新操作多的集合,比如 listeners / observers 集合
- CopyOnWriteArrayList
Queue/Deque
- ArrayBlockingQueue
- 特点:基于数组实现的一个有界阻塞队,大小不能重新定义
- ConcurrentLinkedQueue
- 特点:基于链表实现的无界队列
- DelayQueue
- LinkedBlockingQueue / LinkedBlockingDeque
- 特点:可选择有界或者无界基于链表的实现
- LinkedTransferQueue
- 特点:基于链表的无界队列
- SynchronousQueue
- 特点:有界队列
- ArrayBlockingQueue
Map
- ConcurrentHashMap
- ConcurrentSkipListMap
并发有序
Set
- ConcurrentSkipListSet
- CopyOnWriteArraySet
并发
线程
创建
- 继承
Thread
并重写run()
方法 - ThreadExample.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
public class ThreadExample extends Thread { // run() method contains the code that is executed by the thread. @Override public void run() { System.out.println("Inside : " + Thread.currentThread().getName()); } public static void main(String[] args) { System.out.println("Inside : " + Thread.currentThread().getName()); System.out.println("Creating thread..."); Thread thread = new ThreadExample(); System.out.println("Starting thread..."); thread.start(); } }
- 实现
Runnable
接口 - RunnableExample.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
public class RunnableExample implements Runnable { public static void main(String[] args) { System.out.println("Inside : " + Thread.currentThread().getName()); System.out.println("Creating Runnable..."); Runnable runnable = new RunnableExample(); System.out.println("Creating Thread..."); Thread thread = new Thread(runnable); System.out.println("Starting Thread..."); thread.start(); } @Override public void run() { System.out.println("Inside : " + Thread.currentThread().getName()); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
public class RunnableExampleAnonymousClass { public static void main(String[] args) { System.out.println("Inside : " + Thread.currentThread().getName()); System.out.println("Creating Runnable..."); Runnable runnable = new Runnable() { @Override public void run() { System.out.println("Inside : " + Thread.currentThread().getName()); } }; System.out.println("Creating Thread..."); Thread thread = new Thread(runnable); System.out.println("Starting Thread..."); thread.start(); } }
- 继承
休眠
- 使用
sleep()
- 使用
等待
- 使用
join()
- 使用
线程池
Executors 框架
- 优点
- 线程创建
- 线程管理
- 任务提交和执行
- 方法
execute
- 执行任务submit
- 提交任务shutdown()
- 停止接受新任务,等待先前提交的任务执行,然后终止执行程序shutdownNow()
- 中断正在运行的任务并立即关闭执行程序
- Code - - ExecutorsExample.java
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
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class ExecutorsExample { public static void main(String[] args) { System.out.println("Inside : " + Thread.currentThread().getName()); System.out.println("Creating Executor Service with a thread pool of Size 2"); ExecutorService executorService = Executors.newFixedThreadPool(2); Runnable task1 = () -> { System.out.println("Executing Task1 inside : " + Thread.currentThread().getName()); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException ex) { throw new IllegalStateException(ex); } }; Runnable task2 = () -> { System.out.println("Executing Task2 inside : " + Thread.currentThread().getName()); try { TimeUnit.SECONDS.sleep(4); } catch (InterruptedException ex) { throw new IllegalStateException(ex); } }; Runnable task3 = () -> { System.out.println("Executing Task3 inside : " + Thread.currentThread().getName()); try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException ex) { throw new IllegalStateException(ex); } }; System.out.println("Submitting the tasks for execution..."); executorService.submit(task1); executorService.submit(task2); executorService.submit(task3); //executorService 会一直监听新的任务(即阻塞线程),直到关闭他为止 executorService.shutdown(); } }
- 优点
线程池
- 简介:与
Runnable
或Callable
任务分开存在的一堆工作线程,由executorService
管理 - 机制:任务通过
Blocking Queue
提交到线程池- 如果任务的数量大过活动线程数量,则会将他插入
Blocking Queue
中,一直等到有可用线程为止 - 如果
Blocking Queue
已满,则拒绝新任务
- 如果任务的数量大过活动线程数量,则会将他插入
- Code
- 简介:与
Callable
与Future
- 方法
cancel()
: 尝试取消执行任务,如果成功取消则返回true,否则返回falsecancel(boolean mayInterruptIfRunning)
: 当 mayInterruptIfRunning 为 true 时,则当前正在执行任务的线程将被中断,否则将允许正在进行的任务完成isCancelled
: 任务是否被取消isDone
: 任务是否已完成
- Code - FutureAndCallableExample.java
- 方法
死锁/活锁/饥饿锁 乐观锁/悲观锁
- 死锁 - 其中两个或多个线程永远被阻塞,互相等待
- 活锁 - 其中两个线程一直在让资源,都无法使用资源
- 饥饿锁 - 其他线程一直占用资源,导致永远获取不到资源
- 乐观锁 - 假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性
- 悲观锁 - 假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作
CountDownLatch/Semaphore
CountDownLatch
作用 - 允许一个或多个线程等待,直到在其他线程中执行的一组操作完成
方法
await()
await(long timeout, TimeUnit unit)
countDown()
Code
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
private static int LATCH_SIZE = 5; private static CountDownLatch doneSignal; public static void main(String[] args) { try { doneSignal = new CountDownLatch(LATCH_SIZE); // 新建5个任务 for(int i=0; i<LATCH_SIZE; i++) new InnerThread().start(); System.out.println("main await begin."); // "主线程"等待线程池中5个任务的完成 doneSignal.await(); System.out.println("main await finished."); } catch (InterruptedException e) { e.printStackTrace(); } } static class InnerThread extends Thread{ public void run() { try { Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + " sleep 1000ms."); // 将CountDownLatch的数值减1 doneSignal.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } } }
Semaphore - 信号量
- 方法
acquire()
acquire(int permits)
release()
release(int permits)
- 方法