JUC并发编程

JUC

进程和线程

进程:一个程序,QQ,微信,

一个进程至少包含一个线程,可以有多个线程

java默认有2个线程。main线程和GC线程

线程:

Java: Thread Runable Callable

java无法直接开启线程,是用的本地方法开启的。

并发和并行

  • 并发:多个线程操作同一个资源。单核CPU

  • 并行:多个人一起行走。多个CPU

并发编程的的本质:充分利用CPU的资源

线程

线程的状态

新生、运行、阻塞、等待(死等)、超时等待、终止

wait和sleep的区别

1.来自不同的类,Object.wait Thread.sleep

TimeUnit.SECONDS.sleep(1000);//睡1000秒

2.关于锁的释放

wait会释放锁

sleep抱着锁睡觉,不会释放锁

3.使用的范围是不同的

wait只能在同步代码块中使用

sleep可以在任何地方使用

4.是否需要唤醒

wait需要被唤醒 notify

sleep到时自动唤醒

Lock

传统Synchronize

synchronize 本质:队列,锁

Lock接口

三个实现类:

  • ReentrantLock 普通可重入锁

  • ReentrantReadWriteLock.ReadLock 读锁

  • ReentrantReadWriteLock.writeLock 写锁

Lock lock = new ReentrantLock();默认是非公平锁
Lock lock = new ReentrantLock(true);公平锁

公平锁:十分公平,排队获取锁

为什么默认不是公平锁。如果两个任务 一个3h,一个3s。3s排在3h后面的话就要等3小时才能获取到锁。

非公平锁:可以插队,synchronize也是非公平锁

Lock和synchronize的区别

1.synchronize是一个关键字,Lock是一个接口

2.synchronize无法获取到锁状态,Lock可以判断是否获取到了锁

3.synchronize是全自动的,会自动释放锁。Lock需要手动解锁

4.synchronize 线程1获得锁之后线程2会一直等待;Lock不一定会等待下去。tryLock

5.synchronize 可重入,非公平,不可中断;Lock 可重入锁,可以自己设置公平不公平,可以判断锁

6.synchronize 适合锁少量的代码块,Lock适合锁大量的代码块

锁是什么,如何判断锁是谁的?

这里的synchronized锁的是调用该方法的对象
pubicl void synchronized test(){
...
}

这里的synchronized锁锁的是当前类
pubicl static void synchronized test(){
...
}

集合

对集合并发操作,会出现ConcurrentModificationException 并发修改异常

List

解决并发修改异常的方法

  • 1. Collections.synchronizedList() -- synchronized (mutex) {list.add(index, element);}
  • 2. new CopyOnWriteArrayList<>();-- 用的lock锁,写时复制,每次新增一个元素时,直接复制以前的元素到新的一个list
  • 3.new Vector<>(); 最早出现jdk1.0 直接锁整个方法,效率差

Set

Collections.synchronizedSet(new HashSet<>());

HashSet

实际上就是一个hashmap
public HashSet() {
map = new HashMap<>();
}
add方法就是put一个key。value是固定的
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}

Map

Collections.synchronizedMap(new HashMap<>());
new ConcurrentHashMap<>(); //推荐使用
new Hashtable<>();

callable

callable特点

1.有缓存

2.通过futuretask.get()阻塞,并获取结果

public class CallableTest {
public static void main(String[] args) throws Exception{
FutureTask futureTask = new FutureTask(()->{
System.out.println(123);
return "123";
});
new Thread(futureTask,"A").start();
new Thread(futureTask,"B").start(); //只会打印一遍123,取得是缓存
futureTask.get();
}
}
class MyThread implements Callable{
@Override
public String call() throws Exception {
return "123";
}
}

读写锁

队列

[图片上传失败...(image-bf7888-1642649477663)]

启动多少个线程

CPU密集型和IO密集型

CPU密集型:根据CPU核心数来,跟CPU核心数保持一致最好

IO密集型:设置2倍io任务数

四大函数式接口

Lamab 链式编程 函数式接口 stream流式计算

函数式接口:只有一个方法的接口 ,只要是函数式接口就可以用lamab简化,实际上是匿名内部类

@FunctionalInterface
public interface Runnable {
public abstract void run();
}

foreach()//需要一个consumer函数式接口参数

[图片上传失败...(image-904e85-1642649477663)]

函数型Function 传入一个参数T返回一个类型R

断定型 传入一个参数,返回一个boolean

消费型Consumer 传入一个参数,没有返回值

供给型Supplier 没有参数,返回一个对象

Stream流式计算

你可能感兴趣的:(JUC并发编程)