多线程知识

1-线程基础:
1.多线程的线程池最大数一般是按照你的CPU核数+1
2.cup的调度原理:时间分片,一个线程分配的时间分片固定,当线程执行时间大于时间时间分片时就会有线程切换
3.线程三大要素:原子性,可见性,有序性
4.start与run的区别,start是重建一个线程,run是在原有线程上执行
5.thread类;runnable接口,Callable有future结果

2-volatile
1.只有可见性和有序性(JMM控制)防止重排序(底层还是使用lock保证有序),但是没有原子性
2.重排序:计算机在不影响线程执行结果的情况下,计算机最大限度的发挥机器性能,会对机器指令重新排序优化
3.多线程读,1个线程写时使用volatile能保证可见性(1个线程的修改内存数据,及时同步到JVM内存或者硬件内存,以便下个线程能拿到最新的值)
4.volatile主要用在状态标识,double check的业务场景中
5.遵循:happens-before和as-if-servial原则:这个地方就是程序编写时需要规范
6.volatile变量规则:对同一个变量的写操作先行于后面对这个变量的读操作,写操作会导致其他线程中的缓存失效
程序员编写程序时 :对同一个volatile变量的写操作 先行发生于后面对这个变量的读操作。问题就解决啦

3-threadLocal:
https://gitchat.csdn.net/activity/5f80a1d21772090f20e12b0f
1.定义变量时,容易内存泄露,需要调用Remove方法删除threadlocalMap的value值,因为是若引用用,在垃圾回收时容易回收key,而value没有回收
2.ThreadLocal 是线程的局部变量, 是每一个线程所单独持有的,其他线程不能对其进行访问
3.TreadLocal 多线程,每个线程有一个threadlocalMap,存线程变量副本,这样就可以解决多线程锁的问题
4.当线程池的核心线程数为1时,不管主线程多次修改threadlocal变量的值多少次,所有子线程都只获取主线程第一次设置的变量值;JDK8 增加了InheritableThreadLocal类 可以子线程调用主线程的值
5.通常是类中的 private static 字段,是对该字段初始值的一个拷贝,它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联,最常见的ThreadLocal使用场景为 用来解决 数据库连接、Session管理等。
6.ThreadLocal优雅关闭,应用场景:使用在数据库连接上

3-java.util.concurrent包
https://blog.csdn.net/mingmingzhanghao1/article/details/82215947?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1-82215947-blog-83869742.pc_relevant_aa&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1-82215947-blog-83869742.pc_relevant_aa&utm_relevant_index=2
1.定义的基本数据类型有原子性,实现原理是CAS原理-乐观锁机制和自旋锁实现线程安全性,原子性
2.ConcurrentHashMap与hashtable
1-ConcurrentHashMap数据结构:Segments数组+HashEntry数组+链表,采用分段锁保证安全性
2-jdk1.7结构:1个concurrentHashMap内1个Segment数组,1个segment数组内1个HashEntry数组,每个hashEnry是一个链表结构的元素
jdk1.8结构:Node数据+链表+红黑树
3-1.7JDK segment继承reentrantlock可重入锁,首先将数据分成一段一段的存储,段锁实现并发,volatile保证可见性
1.8JDK 采用synchronized和CAS来实现线程安全
4-hashtable是非线程安全,只能采用synchronized关键字实现锁,所以安全上,性能上差。
3.CopyOnWriteArrayList:用于读多写少并发场景,线程安全,写时复制一个新的数组,通过锁来控制,写未完成成功,读就是读取的是旧数据,成功后读取的是新数据
与arrylist的区别,内部有reentrantlock锁,读写分离,保持最终一致性,不适合大数据量,容易GC
4.ReentrantLock(可重入锁),支持公平锁和非公平锁,支持中断锁功能,基于AQS,排他锁,synchronized不支持中断由JVM控制
5.ReentrantReadWriteLock 运行多个读线程同时访问,不支持读写,写写同时访问
https://blog.csdn.net/u010316188/article/details/86563098
https://www.cnblogs.com/dennyzhangdd/p/6925473.html

4.ArrayBlockingQueue:底层是数组,容量是固定的,可以保证线程安全,同时只有一个线程获取锁的情况下才可以进行queue.put和queue.take方法
5.DelayQueue:延迟队列,ProrityQueue队列存数据,reentanLock锁来实现线程安全,无界队列
6.linkedBlockingQueue:链表的阻塞队列
7.priorityBlockingQueue:具有优先级的无界队列
8.ConcurrentLinkedQueue:基于链接节点的无界线程安全队列

4-java.util.concurrent.atomic包

5-AQS原理:
java.util.concurrent.locks.abstractQueuedSynchronizer抽象类(同步队列器)
https://blog.csdn.net/wojiushiwo945you/article/details/103612673
1.对锁和同步控制工具的开发
2.内部维护了一个状态state,通过原子更新(CAS)这个状态变量可实现加锁解锁操作
3.要自己实现锁,可以基于AQS,重写tryAcquire,tryRelease,lock,unlock方法
4.FIFO队列,底层数据结构是双向链表

显示锁的底层抽象类
公平锁/非公平锁:线程获取锁是否按照锁的顺序来解锁,公平是必须按顺序解锁;非公平是可以插队
公平锁和非公平锁:公平锁是按照等待时间最久的先用,
lock不会主动释放锁,可中断锁,公平锁;sychronized异常时会释放锁,执行时不能中断,非公平锁

https://blog.csdn.net/zhengzhaoyang122/article/details/110847701
https://blog.csdn.net/tuzongxun/article/details/123170903?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_title~default-0.pc_relevant_antiscanv2&spm=1001.2101.3001.4242.1&utm_relevant_index=3
https://blog.csdn.net/rqc112233/article/details/117729828?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_antiscanv2&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_antiscanv2&utm_relevant_index=1

多线程基础:
https://www.cnblogs.com/xuezhaochang/p/14846211.html
1.thread;2.runnable;3.callable;4.ThreadPoolExecute 线程池
https://www.cnblogs.com/luojack/p/10841117.html
–线程执行默认是没有先后顺序的,随机执行
1.thread.currentThread 获取当前线程
2.getPriority获取当前线程优先级;setPriority设置当前线程优先级
3.isAlive 判断当前线程是否处于活动状态
4.join() 调用该方法的线程强制执行,其他线程处于阻塞状态,等待该线程执行完成,其他线程才开始,方法用在需要等待上一个线程结果的后执行的新线程
5.sleep 让当前线程暂停执行,休眠的线程进入阻塞状态
6.yield 礼让其他线程先运行,线程让步,使当前线程从执行状态(运行状态)变为可执行态(就绪状态)。
7.interrupt 中断线程,只是判断当前的线程是否中断,若中断可以去做其他的事情
8.wait 导致线程等待,进入阻塞状态
9.notify 唤醒当前线程,唤醒1个因Wait等待对象释放的线程
10.notifyall 唤醒所有等待的线程,唤醒所有依赖对象释放的线程
11.停止一个线程,不建议使用stop,建议使用interrupt

线程池:
newCashedThreadPool 没有核心线程,非核心线程无限大,可根据需求创建新线程的线程池,一定时间到期后自动移除未必使用的线程,空闲线程不会使用资源
newFixedThreadPool只有核心线程,没有非核心线程,创建定长的线程池,超过并发数,提交任务到线程池队列等待
newScheduledThreadPool核心线程固定,非核心线程没限制且闲置会被回收,创建定长线程池,支持定时及周期性任务执行
1.先建立安全的线程队列concurrentLinkedQueue;2.新建newScheduleThreadPool主线程个数,然后for循环线程队列,循环中执行schedule方法,并添加参数,每隔多少时间执行1个线程
newSingleThreadPool单线程线程池,保证线程有序执行

线程池提交任务submit和execute方法的区别:
1、execut()可以添加一个Runable任务,submit()不仅可以添加Runable任务还可以添加Callable任务。
2、execut()没有返回值,而submit()在添加Callable任务时会有返回值(再添加Runable任务时也有,不过无意义),可以通过返回值来查看线程执行的情况。
3、如果发生异常submit()可以通过捕获Future.get抛出的异常,而execute()会终止这个线程

如何优雅的关闭一个线程
1.准备阶段,发出终止指令,通过设置中断标识,通知目标线程
2.执行阶段,相应终止指令

多线程中断机制:
1.线程的stop等方法都被放弃了,因为强制终止线程会发生预料不到的严重后果
2.线程只能用interrupt中断,而且不是立即中断,而是发起一个类似信号的东西,通过修改了被调用的线程的中断状态来告知那个线程,说他被中断了,至于什么时候中断,这个是又系统判断,会在一个合适的时候进行中断处理
3.interrupt 实例方法,设置实例中断状态为true,不是立即中断
interrupted 类方法,用来判断当前线程是否已经中断,线程的中断状态就该方法清除
isInterrupted 实例方法,用来判断线程是否中断
注意实例线程的实例,类多线程的类

线程池7大核心参数:
1.核心线程数
2.最大线程数
3.空闲线程存活时间
4.时间单位
5.任务队列
6.线程工厂
7.拒绝策略:抛出异常;丢弃队列最靠前的任务;直接丢弃;调用多线程的线程来执行被拒绝的线程
https://blog.csdn.net/qq_45076180/article/details/108316340?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-0.pc_relevant_antiscanv2&spm=1001.2101.3001.4242.1&utm_relevant_index=3

Java主线程,子线程,守护线程和非守护线程理解:
https://www.cnblogs.com/qiumingcheng/p/8202393.html
1.main线程是启动主线程,非守护线程,主线程执行结束,其他线程一样可以正常执行
2.main线程结束,其他线程也可以理解结束,当且仅当这些子线程是守护线程
3.如何设置线程为守护线程:thread.setDaemon(true)

Java中Lock,tryLock,lockInterruptibly有什么区别?
lock():若lock被thread A取得,thread B会进入block状态,直到取得lock;
tryLock():若当下不能取得lock,thread就会放弃,可以设置一个超时时间参数,等待多久获取不到锁就放弃;
lockInterruptibly():跟lock()情況一下,但是thread B可以通过interrupt中断,放弃继续等待锁

保证线程安全的三个方面:原子性/可见性/有序性
原子性:保证同一时刻资源只能被一个线程修改,其他线程阻塞,例如atomic包,CAS算法,synchronized,Lock
可见性:一个线程对主内存的数据操作对于其他线程是可见的,例如:volatile,synchronized
有序性:happens-before原则

什么是指令重排?
编译器和CPU可以在保证输出结果一样的情况下对指令重排序,使性能得到优化

volatile为什么不能保证原子性?只能可见性和有序性
1.volatile使用用在set或get场景,不适合用在GetandOperate场景(这种场所不原子性,需要加锁)
2.什么是内存屏障?一个cpu指令,插入一个内存屏障,相当于告诉CPU和编译器先于这个命令的必须先执行,后于这个命令的必须后执行
3.你用了volatile,相当于在写操作前插入一个写屏障指令,在读操作前插入一个读屏障指令
你对volatile字段写操作,1.一旦你完成写入,任何访问他字段的线程会得到最新值
4.JVM指令执行volatile时,从load到store到内存屏障,共4步,只是最后一步内存屏障时JVM让变量值所有线程可见,中间记录从load到store是不安全的,中间若有其他cpu修改了值将会丢失

Atomic包下的类:具有原子性和可见性,如何实现的?
1.通过CAS实现原子性,但是会有ABA问题
2.ABA问题的解决思路:版本号,为变量加版本号1A-2B-3A
3.CAS的原理:将内存位置处的数据与预期数值相比较,相等则替换新值,不等则什么都不做;JVM的CAS底层实现是CPU的指令cmpxchg

AQS:
队列同步器,一个抽象类,用来构造锁和其他同步组件的基础框架
1.数据结构:双向链表+waitStatus的int值
2.实现lock接口,结合数据结构进行并发控制
3.ReentrantLock支持公平锁和非公平锁,实现lock接口,其中内部方法公平锁fairSync和非公平锁nonfairSync都是继承AQS抽象类

CAS:compare and swap
AQS:abstractQueuedSynchronizer

如何确保线程安全?
1.不可变final
2.线程封闭:1-
3.工具类:JUC并发容器
1-concurrentHashMap 分段锁
2-CopyOnWriteArrayList
3-AQS

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值