# API-工具类库 (Package java.util
)
# 日期
# Date
类
基本信息
Package java.util
public class Date
- 使用
Date
类对象来表示一个日期。默认创建的对象会获取系统当前时间。
重要方法
格式化日期显示
将字符串转化为日期对象
使用SimpleDateFormat
类向上造型,调用其Date parse(String source)
来转换。
InputDate date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2000-02-01 12:42:15");
将日期对象转换为字符串 使用
SimpleDateFormat
类向上造型,调用其StringBuffer format(Date date)
来转换。
InputString str = new SimpleDateFormat("yyyy年MM月dd日").format(date);
# Calendar
类
基本信息
Package java.util
public abstract class Calendar
- 使用静态方法
static Calendar getInstance()
来获取一个Calendar
类实例。
# 集合
# Collcetion
接口
基本信息
Package java.util
public interface Collection<E>
- 是集合类的顶级接口
- 其中
<E>
是泛型,代表该集合只能存储E
类的数据作为元素(element),且必须是引用数据类型。
如:Collection<String>
限定集合中只能存储String
类的数据。
# List
接口
基本信息
Package java.util
public interface List<E>
- 是一种有序的
Collection
- 元素有序(存入顺序),可重复
- 元素存在下标,可通过下标操作对应的元素
重要实现类
ArrayList
类
- 默认初始容量为10;扩容时,在上一次的基础上扩容一半容量
- 线程不安全的集合
- 内存空间连续
- 增删元素比较慢
LinkedList
类
- 基于链表实现,增删快,查询慢
- 线程不安全的集合
Vector
类
Java 中最早的集合,初始容量是10
内存空间连续
每次扩容1倍
线程安全
使用方法
elements()
来返回枚举重要派生类
Stack
类- 遵循先进后出的原则
- 最先放入的元素称为栈底元素
- 最后放入的元素称为栈顶元素
- 放入——入栈/压栈
- 拿出——出栈/弹栈
# Queue
接口
基本信息
Package java.util
public interface Queue<E>
- 遵循先进先出的原则。
- 是一种特殊的
Collection
- 其线性实现有
ListQueue
# Set
接口
基本信息
Package java.util
public interface Set<E>
- 是散列的
Collection
- 元素不可重复
- 不保证存入顺序
- 基于哈希码存放
- 若添加相同元素则抛弃
使用equals()比较时,比较实际元素
重要实现类
HashSet
类
- 默认初始容量为 16, 加载因子为 0.75F
loadFactor 加载因子/装载因子,float
类型 - 每次扩容一倍
- 是线程不安全的集合
值得注意的是
在数据结构知识中,栈和队列是一种有着特殊规则的线性表。而在 Java 语言中各个集合类之间的继承、实现关系并不完全符合传统数据结构知识。
# 并发
基本信息
Package java.util.concurrent
# BlockingQueue
接口
基本信息
public interface BlockingQueue<E>
重要实现类
ArrayBlockingQueue
类
是基于数组且有界的阻塞队列。重要方法
add(object)
- 非阻塞
- 底层调用
offer()
- 添加溢出抛异常
IllegalStateException: Queue full
offer(object)
- 非阻塞
- 添加溢出返回
false
offer(object, timeout, TimeUnit.xxx)
timeout
期间内一直尝试添加,若超时未添加成功则返回false
put(object)
- 阻塞
remove(object)
- 非阻塞
- 队空,不报错
remove()
- 非阻塞
- 队空则抛异常
NoSuchElementException
poll()
- 非阻塞
- 队空返回
null
poll(timeout, TimeUnit.xxx)
timeout
期间内一直尝试移除队首,若超时未添加成功则返回null
take(object)
- 阻塞
PriorityBlockingQueue
类- 无界
- 不允许元素为空
- 队列中元素对应的类必须实现
Comparable
接口
重写compareTo()
来进行排序- 自然排序,升序
- 不保证迭代遍历时的顺序
- 保证逐个取出时的顺序
SynchronousQueue
类
只能保存单个元素
# BlockingDeque
接口
基本信息
public interface BlockingDeque<E>
- 双向队列
- 继承自
BlockingQueue
# ConcurrentMap
接口
基本信息
public interface ConcurrentMap<K,V>
重要实现类/接口
ConcurrentHashMap
类- 映射底层依靠键值对存储数据,默认大小为 16
- 数组的每一个位置维系了一个链表
- 经过一定位运算分布到 16 个桶中
当元素碰撞时,两元素键对比;若相同,则覆盖。不同则生成链。 - 加载因子
0.75f
避免桶中元素太多影响效率,引入加载因子;
当达到一定规模,如使用到个桶以后时,则对桶的数量扩增。之后重新计算全部哈希码,重新排布(Rehash)
ConcurrentNavigableMap
接口
是一种并发导航映射重要实现类
ConcurrentSkipListMap
类
跳跃表重要方法
headMap(String key)
从头开始,截取到指定的键之前组成的子maptailMap(String key)
从尾开始截取subMap(String fromKey, String toKey)
范围截取
# CountDownLatch
类
基本信息
public class CountDownLatch
- 递减锁
- 在构造时传入,线程执行之后
await()
- 计数线程全部执行完成(进行 countdown 来递减)之后执行
await()
之后的代码 - 适合于不同线程进行计数
实例代码
import java.util.concurrent.CountDownLatch;
public class CouuntDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(2);
new Thread(new Teacher(countDownLatch)).start();
new Thread(new Student(countDownLatch)).start();
countDownLatch.await();
System.out.println("上课");
}
}
class Teacher implements Runnable {
private CountDownLatch countDownLatch;
public Teacher(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
System.out.println("老师进入教室");
countDownLatch.countDown();
}
}
class Student implement Runnable {
private CountDownLatch countDownLatch;
public Student(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
System.out.println("学生进入教室");
countDownLatch.countDown();
}
}
# CyclicBarrier
类
基本信息
public class CyclicBarrier
- 栅栏
- 在构造时传入,需要阻塞的地方
await()
- 没
await()
一次计数减少一次,直到减为 0 放开阻塞 - 适合于同一线程类产生多个线程计数
实例代码
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierDemo {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
new Thread(new Horse("1"), cyclicBarrier)).start();
new Thread(new Horse("2"), cyclicBarrier)).start();
new Thread(new Horse("3"), cyclicBarrier)).start();
System.out.println("开始比赛");
}
}
class Horse implements Runnable {
private String name;
private CyclicBarrier cyclicBarrier;
public Horse(String name, CyclicBarrier cyclicBarrier) {
this.name = name;
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
System.out.println(name + "走到出发点");
try {
cyclicBarrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}
# Exchanger
类
基本信息
public class Exchanger<V>
- 交换机
- 用与交换两个线程的信息
实例代码
import java.util.concurrent.Exchanger;
public class ExchangerDemo {
public static void main(String[] args) {
Exchanger<String> exchanger = new Exchanger<>();
new Thread(new SpyA(exchanger)).start();
new Thread(new SpyB(exchanger)).start();
}
}
class SpyA implements Runnable {
private Exchanger<String> exchanger;
public SpyA(Exchanger<String> exchanger) {
this.exchanger = exchanger;
}
@Override
public void run() {
String msg = "M1";
try {
String exchange = exchanger.exchange(msg);
System.out.println("SpyA 收到 SpyB 的信息:" + exchange);
} catch (InterruputedException e) {
e.printStackTrace();
}
}
}
class SpyB implements Runnable {
private Exchanger<String> exchanger;
public SpyB(Exchanger<String> exchanger) {
this.exchanger = exchanger;
}
@Override
public void run() {
String msg = "M2";
try {
String exchange = exchanger.exchange(msg);
System.out.println("SpyB 收到 SpyA 的信息:" + exchange);
} catch (InterruputedException e) {
e.printStackTrace();
}
}
}
# Semaphore
类
基本信息
public class Semaphore
- 信号量
- 用于限制某段代码在某个时间段内最多只能有规定线程书目进入访问
- 每个线程进入的时候需要进行
acquire()
操作,使得信号量-1
,知道为0
- 若有新的线程来访问则会在
acquire()
操作阻塞,直到之前的某线程release()
实例代码
import java.util.concurrent.Semaphore;
public class SemaphoreDemo {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(5);
for (int i = 0; i < 10; i++) {
new Thread(new FileWatching(semaphore)).start();
}
}
}
class FileWatching implements Runnable {
private Semaphore semaphore;
public FileWatching(Semaphore semaphore) {
this.semaphore = semaphore;
}
@Override
public void run() {
String name = Thread.currentThread().getName();
try {
semaphore.acquire(); // 信号量 -1
System.out.println(name + "领取到了眼镜开始观影");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name + "归还眼镜,离开了影院");
semaphore.release(); // 信号量 +1
}
}
# ExecutorService
接口
基本信息
public interface ExecutorService
- 类似线程池,实现线程复用
- 先交由核心线程处理;若核心线程已满则放入工作队列中;若工作队列满则创建临时线程
实例代码
public class ExcutorServiceDemo {
public static void main(String[] args) {
// corePoolSize: 核心池大小。线程池中核心线程的数量,创建后不再销毁
// maximumPoolSize: 允许存在的最大线程数量
// keepAliveTime:存活时间
// unit: (存活时间的)单位
// workQueue: 工作队列,阻塞式队列。在核心线程都被使用的情况下,新请求会被放在工作队列中
ExecutorService executorService = new ThreadPoolExcutor(5, 10, 3000, TimeUnit.MILLISECONDS, new ArrayBlockingQueue(10));
for(int i = 0; i < 5; i++) {
executorService.submit(new Demo()); // 支持Runnable
// executorService.execute(new Demo()); 支持Callable/Runnable
}
executorService.shutdown();
}
}
class Demo implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "被处理");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
线程池
Executor
提供了三种线程池:CachedThreadPool
、FixedThreadPool
和ForkJoinPool
。
CachedThreadPool
- 缓存线程池
- 小队列大池
- 无核心线程,临时线程存活时间短
- 能够较好应用高并发场景
- 不适合长任务场景
ExecutorService executorService = Executors.newCachedThreadPool();
FixedThreadPool
- 大队列小池(传入数目)
- 所有线程都为核心线程
- 降低服务器的并发压力
ExecutorService executorService = Executors.newFiuxedThreadPool(5);
ForkJoinPool
- 分叉合并(不推荐使用)
Callable 接口
基本信息
public interface Callable<V>
- 泛型表示线程执行后的返回值结果
Callable
只能交给线程池处理
实例代码
class CallableDemo implements Callable<String> {
@Override
public String call() {
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
return "SUCCESS";
}
}
# 锁与原子操作
- 锁
- 类似
synchronized
机制,但更加灵活 - 公平策略与非公平策略
synchronized
为非公平策略Lock
接口
基本信息
Package java.util.concurrent.lockspublic interface Lock
具体实现类
ReentrantLock
类- 默认为非公平策略,可设置为公平策略
- 通过
lock()
上锁,unlock()
解锁
- 读写锁
ReadWriteLock
- 使用时允许多个线程同时使用统一资源,但只允许一个线程对资源进行写操作
- 读期间不允许进行写操作,写期间不允许进行读操作
- 类似
- 原子操作 操作时不允许其他操作
# Iterator
接口
基本信息
Package java.util
public interface Iterator<E>
- 通过指针挪动遍历集合
- 遍历过程中不允许增删原集合
- 若一个对象允许使用 foreach 遍历,该类必须实现
Iterable
接口
# Collections
类
基本信息
Package java.util
public class Collections
操作集合的工具类
重要方法
compare(T o1, T o2)
- 返回正负值来确定大小
- 若为正则第一个数排到第二个数之后;反之排到其前
- 若没有指定排序规则, 必须实现
Comparable
接口,比较规则写在compareTo()
中
# Map
接口
基本信息
Package java.util
Interface Map<K,V>
- 以键-值对形式存在的数据结构,其中键是唯一的
- 遍历
Map
的方法- 获取所有键,通过键来获取值
- 获取键值对组成的集合
重要实现类
HashMap
类
- 默认初始容量是 16, 加载因子为 0.75F
- 每次扩容一倍
- 允许键或值为
null
- 异步式线程不安全的映射,不对映射做安全限制
HashTable
类
- 默认初始容量为 11, 加载因子为 0.75F
- 不允许键或值为
null
- 同步式线程安全的映射
- 对外公开的涉及到键值对的操作方法都是同步方法
- 锁对象是
this
,HashTable
以本身对象作为锁对象
ConcurrentHashMap
类
- 异步式线程安全的映射
- 引入分段锁(分桶锁) 详情见ConcurrentMap
# Properties
类
基本信息
Package java.util
public class Properties
- 是一个可以持久化的映射
- 键和值默认为
String
类型 Properties
对象必须存储到properties
文件中properties
文件中不能存储中文,会变成对应的编码
重要方法
setProperty("键","值")
store(输出流, comments)
load(输入流)
# Scanner
类
基本信息
Package java.util
public final class Scanner
使用Scanner
可以从控制台读取数据。
Scanner sc = new Scanner(System.in);
String name = sc.nextLine();
注意
除了nextLine()
,其余都是以空格为结束符