Map
存储键值对形式的数据 key-value(K-V)
eg.Map<Integer,String>
- key是无序的,不可重复的–>set集合
- value无序的,可重复的 -->Collection集合
- 一个key只能对应一个value(如果想要value对应多个值可以存储在容器中list)
- 存储多个数据的时候,如果key相同,value会覆盖
遍历:
-
keySet() 返回所有的key
-
values() 返回所有的值
-
entrySet() Set<Map.Entry<K,V>
HashMap
底层:哈希表实现
缺点:线程不安全
存储的内容是键值对(key-value)映射
HashMap去重:根据key去重,自定义引用数据类型数据:hashCode()和equals()
Hashtable
基本和HashMap类似:线程安全
TreeMap
底层:红黑树结构
TreeMap去重:根据key去重,自定义引用数据类型数据:
内部和外部比较器
HashMap与TreeMap的区别:作规律排序就用TreeMap,否则用HashMap
Collections
可以操作容器类的工具类
方法列举:
void sort(List)//对容器元素按升序排序
void shuffle(List)//对容器元素进行随机排列
void reverse(List)//对容器元素进行逆序排列
void fill(List,Object)//用特定对象重写整个容器
int binarySearch(List,Object)//二分法寻找特定对象
处理HashMap的线程安全问题
1.使用Hashtable
2.Collections.synchronizedMap(Map)返回一个线程安全的map容器
3.juc包java.util.concurrent类 ConcurrentHashMap<K,V>//比较推荐使用此类
Properties
该类K-V键都是字符串形式数据
用于配置文件来调用:
(创建)src右键->new source folder->new file->db.properties->在内创建键值对形式的数据(eg.uname=scott)
创建对象:
Properties pro=new Properties();
通过IO流的形式加载:
pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream(“db.properties”));
调取db内容:syso(pro.getProperty(“uname”));
多线程:
多个任务同时执行(只当需要多个任务同时执行时才需开启)
优点:资源利用率更好,简化有些程序设计,加快程序响应
进程:对与操作系统而言就是不同的任务执行,每一个进行都有自己的代码和数据空间,进程之间切换消耗比较大,一个进程中包含一到多个线程,是资源分配的最小单位
线程:一系列线程共享代码和数据空间,线程之间切换消耗较小,线程是cpu调度的最小单位
三高: 高可用(数据不会出错) 高性能(用户体验度好) 高并发(多用户同时操作抢购)
关注重点:
1.多线程的创建方式(3种)
1)继承Thread类 重写run()方法
2)实现Runnable接口,重写run()方法 --推荐
3)实现Callable接口,重写call()方法–了解 juc
2.保证线程安全问题 同步
3.线程状态
1)继承Thread类 重写run()方法
开启线程:Thread->start()开启线程(需要main中创建对象,利用Thread类的对象进行直接调用,eg.th.start())
2)实现Runnable接口,重写run()方法 --推荐
好处:避免带线程的局限性 实现资源共享
开启线程:使用Tread类中的start()方法开启 (静态代理)
调用方式比如:new Thread(类的对象).start();
应用例子:龟兔赛跑
3)实现callable接口,重写call方法
优点:可以抛出异常,可以存在返回值
缺点:使用复杂麻烦
步骤:创建指定线程池数量
eg.ExecutorService es=Executors.new FixedThreadPool(2);
创建了两个线程
线程的状态:
新生状态 : new,每个线程都有自己的运行空间
就绪状态 : start(),就绪不代表运行,代表线程具有可运行的能力,在就绪队列中排队等待cpu调度
运行状态 : cpu把时间片分配给某个线程,这个线程就就行运行状态
阻塞状态 : sleep()…
终止状态 : 执行完毕
注意:
- 1)一个线程一旦进入到阻塞状态,阻塞解除无法直接回复运行状态,进入就绪状态等待cpu的调度
- 2)一旦一个线程以终止,无法恢复,如果创建开启,也是新的线程
终止状态的几种情况:
- 1)正常执行完毕
- 2)强制结束 stop(),destroy(),方法已过时,不推荐使用
- 3)通过标识进行控制–推荐
进入就绪状态的情况:
- 1.start()
- 2.阻塞状态结束
- 3.yield()
- 4.线程切换,被切换的线程进入到就绪状态
进入阻塞状态的情况:
- 1.sleep()
- 2.wait()
- 3.join()
- 4.IO操作
sleep使用:
1.加剧和查询方法发生问题的可能性
2.模拟网络延时
线程状态的检测
Thread.State以及 getState()
线程优先级: void setPriority(int newPriority)
更改线程的优先级。 提高先执行的概率,但不是绝对的
1~10 最小是1 最大是10 默认5
MAX_PRIORITY -->10
MIN_PRIORITY -->1
NORM_PRIORITY -->5
getPriority() 获取线程优先级别
eg. th.setPriority(Thread.Max_PRIORITY)
(th为Thread的对象)
线程安全问题:
多线程同时操作同一资源时可能出现的不安全问题(比如重复多次出现同一数值)
处理线程安全:
同步锁 synchronized
同步方法: 效率较低,简单
同步静态方法
同步成员方法
同步块: synchronized(this|类名.calss|资源(成员属性)){…}
锁this:锁住对象所有的成员属性,若只需锁一个资源,则直接锁资源。
锁资源,效率较高
资源变成自定义类型–>锁对对象的地址(不变)
注意:
1.锁一定要锁不变的内容 自定义类型对象地址
2.锁的范围太大,效率低,锁的范围太小锁不住
double check 双重检查 效率高,锁的范围小
锁静态方法,锁类的class对象都是锁类,锁住了这个类的所有对象
如懒汉单例模式的锁:
public static SingleTon newInstance(){
if(single==null){//检查①
synchronized (SingleTon.class) {//检查②
Thread.sleep(200);//此处为异常
if(single==null){
single=new SingleTon();
}
}
}
return single;
}