JUC (java.util.concurrent)
1.1 进程/线程
1.2 并发和并行有什么区别?
并发就像是秒杀一样,多个线程去访问同一个资源。并行各种事情一路并行去做
JUC的三个包
java.util.concurrent
java.util.concurrent.atomic(原子性)
java.util.concurrent.locks(锁)
3个售票员 卖出30张票
1.高内聚 ,低耦合的前提下 线程 操作 资源类
1.1 一言不合,先创建一个资源类
class Ticket{ //资源类 = 实例变量 + 实例方法
private int number = 30;
Lock lock = new ReentrantLock();
public void sale(){
lock.lock();
try{
if(number>0){
sout(Thread.currentThread().getName());
}
}catch(Exception e){
e.printStackTrace
}finally{
lock.unlock();
}
}
}
main{ //主线程,一切线程的入口
Ticket ticket = new ticket();
new Thread(()->{for(int i = 1; i<=40;i++)ticket.sale();},"A").start;
new Thread(()->{for(int i = 1; i<=40;i++)ticket.sale();},"B").start;
new Thread(()->{for(int i = 1; i<=40;i++)ticket.sale();},"C").start;
/************
new Thread({
@Override
public void run(){
for(int i = 1; i<=40;i++){
ticket.sale();
}
}
},"AA").start();
new Thread({
@Override
public void run(){
for(int i = 1; i<=40;i++){
ticket.sale();
}
}
},"BB").start();
new Thread({
@Override
public void run(){
for(int i = 1; i<=40;i++){
ticket.sale();
}
}
},"cc").start();
//Thread t1 = new Thread();
//Thread t2 = new Thread();
//Thread t3 = new Thread();
}
synchronize 重锁
Lock ReentrantLock 可重入锁/递归锁
java获得多线程有四种方法:
1.继承Thread类
2.实现Runnable接口
3.实现Callable接口通过FutureTask包装器来创建Thread线程
4.通过线程池
线程的启动不是以start()为转移,而是等待底层操作系统和CPU的调度
start就是一个就绪,发生了线程调度才会执行
多线程有几种状态 (6)
new
Runnable(就绪)
Blocked(阻塞)
WAITING(等待)
waiting和wait不是一回事,waiting是一个状态,wait是一个方法
TIMED_WAITING()
Timed_waiting 和 waiting的区别 time_waiting是过时不候,waiting是一直等
Terminated()
接口是特殊的类,类就可以new
new一个接口 叫做匿名内部类 然后 new一个类 ,多肽
函数式编程 lambda表达式 单方法的匿名内部类 @FuncationalInterface
拷贝小括号,写死右箭头,落地大括号
default(定义 + 实现)
综上
new Thread(()->{for(i=0;i<=40;i++)ticket.sale();},"名字").start
new ArrayList 底层是new什么
new 一个数组
数组都有类型,Arraylist 底层是什么类型
Object
默认容量是多少
java7 是 10
java8 是空引用,当第一次调用add扩容到10. hashmap默认是16
java8 new 一个 arraylist底层是new一个初始值为10的数组
怎么扩容的 10 - 15 - 22 - 33
第一次扩容 是原值的一半 拷贝方法 Arrays.copyOf()
第二次扩容 原值的一般
而hashmap 扩容是原值的一倍 ,向右移一位
ArrayList 是否线程安全
否
例: 1.故障现象
java.util.ConcurrentModificationException(业务还没实现完了,就被另一个线程打断)
2.导致原因
多线程 并发争抢同一个资源类且没加锁
3.解决方法
3.1 加锁? new Vector<>();add没有锁,又不可能给arraylist的add加锁,这是需要用到同List中的线程安全vector中的add去进行操作
3.2 Collections.synchronizedList(new Arraylist<>())
3.3 new CopyOnWriteArrayList()
4.优化建议
new CopyOnWriteArrayList();
List
list.add("a");
list.add("a");
list.add("a");
list.forEach(system.out::println)
就一个线程 ,安全
当多个线程时暴露线程不安全
List<string> list = new ArrayList<>();
List<string> list = new vector<>(); // 如果不能使用vector 呢
List<string> list = Collections.synchronizedList(new Arraylist<>()); //用collections
List<string> list = new CopyOnWriteArrayList();
for(int i = 1;i<=3; i++){
new Thread(()->{
list.add(uuid.randomUUID().tostring().substring(0,8));
sout(list)
}),String.valueOf(i).start();
}
collection和collections的区别
collection是集合类的上层接口,collections是集合框架的工具类
那arraylist存在的意义是什么呢?
此时就涉及到 效率和安全了
当遇到一致性为首要目的时,就需要用到vector
当遇到效率作为首要目的时,就用到arraylist
那CopyOnWriteArrayList 那为什么那么猛呢
它读的时候共同读,写的时候单另写
写完以后代替上一次版本,写的时候被读,读的是没写之前的/还是阻塞?,
又迸发出来的小问题 ———— lock和 synchronize 的区别又是什么,reentrantlock和synchronized区别,volatile又是怎样的呢
那set 安不安全
不安全
解决COW copyonwriteset
hashset底层数据结构是什么
hashmap,hashmap底层 是 数组 + 链表 + 红黑树
hashset是hashmap的key的部分
value是数组
hashset的add
hashset.add(E e) = map.put(e,PRESENT)== null
list、set、map都线程不安全的