标签:tps rip ESS sync tco jps one new 饿汉式单例模式
JUC是java中java.util.concurrent工具类的缩写
进程:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。
线程:一个进程中至少有一个线程。线程可以利用进程所拥有的资源,在引入线程的操作系统中,通常都是把进程作为分配资源的基本单位,而把线程作为独立运行和独立调度的基本单位,由于线程比进程更小,基本上不拥有系统资源,故对它的调度所付出的开销就会小得多,能更高效的提高系统多个程序间并发执行的程度。
并发:单核,多线程操作一个资源
并行:多核,多线程可以同时运行

并发编程的本质:充分利用CPU资源
wait:会释放锁,有异常
sleep:不会释放锁,有异常
Lock锁(重点):
什么是锁:
synchronize:锁定资源
Lock:
公平锁:先来后到
非公平锁:可以插队
synchronize与lock的区别:
synchronize代码块里面为什么要用while而不是if
我们知道当线程执行到wait()方法时,会一直进行等待,直到被幻醒notify()或notifyAll()才会继续执行代码;如果用if的话,会不执行if中的条件,因为在执行wait()时已经执行了条件语句;而用while的话会继续执行条件语句,从而不会出现虚假唤醒的问题。
JDK文档:

在synchronize使用if

在synchronize使用while

Lock+Condition实现PC
package com.lyt;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @description :说明
*/
public class LockPCTest {
public static void main(String[] args) {
final PC pc = new PC();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
pc.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A").start();new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
pc.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"B").start();new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
pc.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"C").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
pc.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"D").start();
}
}
class LockPC {
private int number=0;
Lock lock=new ReentrantLock();
Condition condition=lock.newCondition();
//生产
public void increment() throws InterruptedException {
lock.lock();
try {
while (number!=0){
condition.await();
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
number++;
System.out.println("当前线程"+Thread.currentThread().getName()+":"+number);
condition.signalAll();//通知其它线程已生产
}
//消费
public void decrement() throws InterruptedException {
lock.lock();
try {
while (number==0){
condition.await();//等待
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
number--;
System.out.println("当前线程"+Thread.currentThread().getName()+":"+number);
condition.signalAll();//通知其它线程已消费
}
}
condition比synchronize的优势:能够精确的唤醒线程
利用Condition使多线程按照自己定义的顺序执行
class LockPC1 {
private int number = 1;
Lock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
Condition condition3 = lock.newCondition();
public void A() throws InterruptedException {
lock.lock();
try {
while (number != 1) {
condition1.await();
}
System.out.println("AAAAAAAAAAAAA " + Thread.currentThread().getName() + ":" + number);
number=2;
condition2.signal();//通知线程2
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void B() throws InterruptedException {
lock.lock();
try {
while (number != 2) {
condition2.await();//等待
}
System.out.println("BBBBBBBBBBBBB " + Thread.currentThread().getName() + ":" + number);
number=3;
condition3.signal();//通知线程3
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void C() throws InterruptedException {
lock.lock();
try {
while (number != 3) {
condition3.await();//等待
}
System.out.println("CCCCCCCCCCCCCCCCC " + Thread.currentThread().getName() + ":" + number);
number=1;
condition1.signal();//通知线程1
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
集合不安全:
多线程操作集合可能存在不安全,如ArrayList,HashMap等
安全集合有哪些:

(concurrent下的集合使用Lock锁,vector使用synchronize锁,使用前者的性能高)
HashSet用的是HashMap,
concurrentHashMap的原理推荐文章:https://www.jianshu.com/p/865c813f2726
Callable
靠FutureTask类来适配Runable接口,来启动线程
可以有返回值
可以抛出异常
方法不同,run()/call()
辅助类
countDownLatch(减法计数器)等线程执行完在执行await
CyclicBarrier(加法计数器)等线程执行完在执行await
Semaphore(信号量)等线程执行完在执行await
Semaphore.acquire()获取,已满则等待,直到释放
Semaphore.release()释放,信号量+1,唤醒其他线程
作用:限流,多线程操作互斥资源
读写锁:
ReaderWriteLock
class DataTest{
private Map map=new HashMap();
private ReadWriteLock readWriteLock=new ReentrantReadWriteLock();
public void write(String a,String b){
try {
//只能由一个线程写入完成,才能执行其他线程(独占锁)写锁
readWriteLock.writeLock().lock();
System.out.println(Thread.currentThread().getName()+"写入前");
map.put(a,b);
System.out.println(Thread.currentThread().getName()+"写入后");
} catch (Exception e) {
e.printStackTrace();
} finally {
readWriteLock.writeLock().unlock();
}
}
public void reader(String a){
try {
//加不加读取锁都一样,因为是多线程共享(共享锁)读锁
// readWriteLock.readLock().lock();
System.out.println(Thread.currentThread().getName()+"读取前");
map.get(a);
System.out.println(Thread.currentThread().getName()+"读取后");
} catch (Exception e) {
e.printStackTrace();
} finally {
// readWriteLock.readLock().unlock();
}
}
}
阻塞队列
阻塞
队列(FIFO)
BlockingQueue
四组API

synchronizeQueue
最多放一个元素,也就是说进去一个,等取出来在进去
线程池(重点)
池化技术
不用用Executors去创建线程池(不安全),用ThreadPoolExecutor的方法去创建,因为这样可以减少资源的耗消
优点:
降低消耗
提高响应的速度
方便管理
线程池的三大方法

创建线程池都调用

七大参数
public ThreadPoolExecutor(int corePoolSize,//核心线程池大小
int maximumPoolSize,//最大核心线程池大小
long keepAliveTime,//起始了没有调用就会释放
TimeUnit unit,//超时单位
BlockingQueue<Runnable> workQueue,//阻塞队列
ThreadFactory threadFactory,//线程工厂,创建线程的,一般不用动
RejectedExecutionHandler handler//拒绝策略
) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
线程池的四种拒绝策略
ThreadPoolExecutor.AbortPolicy(默认):丢弃任务并抛出RejectedExecutionException异常。 ThreadPoolExecutor.DiscardPolicy:丢弃任务,但是不抛出异常。 ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新提交被拒绝的任务
ThreadPoolExecutor.CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务
最大线程如何去定义(调优)?
CPU密集型,几核的CPU就定义多少,效率最高
IO密集型,根据程序的耗IO的线程,大于该线程就好啦
最大线程池的触发:线程数大于(maximumPoolSize+workQueue),触发最大线程池后会执行拒绝策略
自定义创建线程池:
public class PoolTest {
public static void main(String[] args) {
ExecutorService executorService=new ThreadPoolExecutor(
2,
Runtime.getRuntime().availableProcessors(),//获取CPU的核数
3,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(2),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardOldestPolicy()
);
try {
for (int i = 1; i <= 4; i++) {
executorService.execute(()->{
System.out.println(Thread.currentThread().getName());
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
executorService.shutdown();
}
}
}
四大函数式接口(重点)
四大知识点:lambda表达式“()->{}”、链式编程“xxx().xxx().xxx()”、函数式接口、Stream流式计算
函数式接口:只有一个方法的接口,如Runnable接口,框架大量使用
Function函数式接口(用创造于工具类)
有一个输入T,有一个返回R

lambda表达式使用Function函数接口:
![]()
Predicate函数式接口(用于写判断工具,比如判断是否为空)
有一个参数,返回一个Boolean类型的值

lambda表达式使用Predicate函数接口:
![]()
Consumer(消费)函数式接口
有一个输入,没有返回值

Supplier(供给)函数式接口
没有输入,只有返回值

lambda表达式使用Consumer、Supplier函数接口:

Stream流式计算
什么是Stream流式计算
计算应该交给Stream流(java.util.Stream)
使用Stream的推荐文章:https://www.cnblogs.com/balloon72/p/13177916.html
ForkJoin(分之合并),思想拆分=》分治法
jdk1.7后的,并行执行任务,提高工作效率
特点:工作窃取,简单说线程自己的任务完成了,就会窃取别线程的任务,从而提高效率
异步回调
future的实现类CompletableFuture类(类似ajax)
一个线程向另外一个线程发出异步请求
JMM
volatile是java虚拟机提供轻量级的同步机制
什么是JMM(java内存模型):(推荐文章:https://www.jianshu.com/p/8a58d8335270)
内存交互操作有8种,虚拟机实现必须保证每一个操作都是原子的,不可在分的(对于double和long类型的变量来说,load、store、read和write操作在某些平台上允许例外)
JMM的约定
指令重排(你写的程序并不是按照你的顺序执行的)
源代码==》编译器优化重排序==》指令级并行重排序==》内存系统重排序==》执行指令
单例模式(要构造器私有private)
饿汉式单例模式(直接new)
懒汉式单例模式(要用才new)
懒汉式单例模式(单锁)(先检测是否创建再要用才new)
懒汉式单例模式(DCL=双重检查)(先检测是否创建再判断是否存在实例,再要用才new)
不是一个原子性操作,也就是说不是按照如下123,的顺序执行可能按照321顺序执行,所以在该方法中加关键字volatile防止指令重排
反射可以忽视私有的构造器,所以可以破坏有私有构造器的单例模式
枚举(enum)的单例模式解决java反射的破坏单例模式
深入CAS(compareAndSet=比较并交换):比较当前工作中的值和主内存的值,如果这个值是期望的,则执行操作,如果不是就一直循环,因为他有自旋锁
在AtomicInteger类里,如果达到了expect,则update,否则不更新,CAS是CPU的并发原语

缺点:
Unsafe类直接调用本地接口操作内存

锁
可重锁(递归锁)(简单理解锁中锁)
多线程,全部线程执行完a,再执行b

自旋锁

死锁:两把锁相互占用对方所需的资源并且不释放该资源
检测死锁:jps -l

查看:

完结。。。
标签:tps rip ESS sync tco jps one new 饿汉式单例模式
原文地址:https://www.cnblogs.com/lyt-echso/p/13190386.html