线程安全:线程安全就是多个线程同时操作同一个对象时,数据永远准确的情况
线程不安全:多个线程同时操作同一个对象时,存在数据不准确的情况,这就是线程不安全
如何解决线程不安全?
加锁!
synchroniazed的使用可以解决数据不准确的问题,synchronized就是锁,针对多线程进行线程安全的控制
所具备的特点:互斥:相互排斥。重入:重复进入,同一个线程可以重复的抢得该锁
synchronized关键字的使用场合:可以作用在代码块和方法两个地方
线程同步:数据永远可以保证准确的,但是效率非常低下
注意:1、如果时非静态方法,此时锁就是该对象的锁
2、如果该方法时静态方法,那么此时锁就是该对象的锁
面试题
synchronized(this){}
此时,获得的是谁的锁?答案:对象自身
synchronized(类.class){}
此时,获得的是谁的锁?答案:类对象自身
public synchronized void 方法(){}
此时,获得的是谁的锁?答案:对象自身
public static synchronized void 方法(){}
此时,获得的是谁的锁?答案:类对象自身
线程同步的方法:wait(),notify(),notifyall()
思考if和while在此处的区别
- publicclassThreadStudy{
- publicstaticvoid main(String[] args){
- PrintResource pr =newPrintResource();
- // 定义3个线程
- Thread t1 =newThread(()->{
- pr.println(“A”,”B”);
- });
- Thread t2 =newThread(()->{
- pr.println(“B”,”C”);
- });
- Thread t3 =newThread(()->{
- pr.println(“C”,””);
- });
- t1.start();
- t2.start();
- t3.start();
- }
- }
- classPrintResource{
- String current =”A”;
- publicsynchronizedvoid println(String str,String next){
- //为什么要用while 原因是:需要多次判断,此次,是否应该由 你这根线程来打印
- while(!Objects.equals(current, str)){
- try{
- wait();//等待期间,会释放 线程锁
- }catch(InterruptedException e){
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- System.out.println(str);
- current = next;//设置下一个需要打印的
- notifyAll();
- }
- }
leep() 与 wait() 的区别:
(1)、sleep() 是休眠,时间到了会自动唤醒,而wait() 是等待,需要其他线程调用notifyall() 来唤醒
(2)、sleep() 在休眠期间,不会释放线程手上的锁资源,而wait() 在等待期间,会自动释放
(3)、sleep(5000) 意味着:线程一定需要休眠5S钟,而且不会被唤醒
wait(5000)意味着:线程需要等待5S钟,但随时可以被notifyall() 唤醒
连接池:管理和复用连接的池
线程池:管理和服用连接的池
对象池:管理和复用对象池的spring框架!
线程池的组成:1、任务队列:让任务按照queque方式进行排序
2、工作线程:用来执行任务的线程
3任务对接接口:用来接受外部任务的接口
4、线程管理器:用来管理线程的类
简单线程池的用法:Executors.
复杂线程池ThreadPoolExecutor有七个参数需要记住,面试题!
corePoolSize:初始化多少个线程
maximumPoolSize:最多线程池可以存放多少个线程
keepAliveTime:每根空闲线程,可以在线程中存活多久
Unit:时间单位
WorkQueue:任务队列
TreadFactory:线程工厂,作用是创建线程
Handle:拒绝策略
拒绝策略:当任务队列满了,新任务来临,应该怎么办?
ThreadPoolExecutor.AbortPolicy (默认)新任务来临,直接丢弃,然后抛出异常
ThreadPoolExecutor.CallerRunsPolicy 由提交任务的线程,去执行任务
ThreadPoolExecutor.DiscardOldestPolicy 抛弃 任务队列中等待时间最长的任务,然后将新任务追加到队列的尾部
ThreadPoolExecutor.DiscardPolicy 新任务来临,直接丢弃,不抛出异常
生产者消费模式
使用队列来实现数据通信
队列特点时先进先出
生产者消费者模式借助Queue队列来实现,Queue的父接口是Collection,有顺序要求
优点:生产者、消费者程序可以直接解耦
解决生产者,消费者处理速度不匹配的问题
死锁:多个程序之间,由于无限期等待对方释放锁资源造成程序无法继续运行的过程
二、死锁的4个条件
(1)、一定使用到互斥锁
(2)、不可剥夺,当某根线程持有某个对象的锁以后,其他线程不能剥夺
(3)、相互等待,线程A等待线程B释放,而线程B等待线程A释放
(4)、请求和保持条件 线程A和线程B 都会无限期的不断再次请求获得对应的锁
解决方案:使用具有时效性质的锁