多线程Java

什么是进程?
当我们启动一个应用程序,就会开启一个进程。
win:通过任务管理器
Linux:ps kill -9
在进程中至少有一个线程,该线程就是主线程
进程就是线程的集合。

什么是线程
一条程序执行的路径

多线程的好处
提高程序的效率
同时的并行的

多线程的应用场景
1异步的实现发送短信,快速提高响应,对用户的体验就非常好
2.异步的记录日志
3.对我们后端接口中比较耗时间的代码都可以采用异步实现。

为什么需要用到多线程
http属于同步,整个过程基于请求和响应的过程,如果服务端没有及时响应给客户端的情况下,就会造成我们客户端一直在等待,用户体验非常不友好。

例如一个登陆功能,如果没有多线程,完成下面操作要8秒,这就可以作为项目中使用多线程优化的部分。!!!

在这里插入图片描述

单线程与多线程执行的区别?
单线程就是从上往下顺序执行,如果中间有个环节出现错误,整个程序中断,
在这里插入图片描述

对于单核CPU服务器,开启多线程的情况下,并不是真正意义上的多线程。因为单核CPU在同一时间最多只能运行一个线程。

多核处理器:比如说6核12线程,在同一时间可以支持12个线程的同时访问。

多线程真的是线程越多越好么
如果在服务器上频繁的开启线程,会导致cpu不断切换,会影响到服务器的性能。
如果项目比较小,可以使用多线程来实现异步,如果项目很大,建议使用mq来实现异步,因为不可能开那么多线程。

多线程的创建方法:
1)继承Thread类
2)实现runnable接口
3)可以带返回结果的线程Callable
采用异步来执行线程,但是如果我们要获得线程返回结果的情况下,整个过程的执行顺序就变成了一个线程。
在这里插入图片描述
4) 线程池
其他扩展方式创建线程:
Spring提供异步直接@Asyn,代理模式实现

在这里插入图片描述
这样的话要8秒才能登陆成功,而且比如说记录日志-loginLog,发送短信-sendSms和发送邮件-sendEmail不应该放主线去做。
在实际项目中,一定要结合线程池,不要new Thread去执行,这样太消耗资源了。
如果在方法上直接加@Asyn,肯定没用,需要新建一个类LoginManage
在业务层,自动注入LoginManage,这样两秒就能响应

在这里插入图片描述
可以看到通过不同的线程去异步执行
在这里插入图片描述
这样写可以获得线程的返回结果
在这里插入图片描述

用户线程和守护线程的区别

用户线程:当我们的主线程停止后,用户线程不会随着主线程而停止
守护线程:当我们主线程停止后,守护线程也会随着主线程停止。
守护线程的应用场景:GC线程
默认创建的线程都是用户线程
Thread.setDaemon(true)变成守护线程】

如何停止一个线程

不用用stop停止线程,因为这时候线程可能还没有执行完毕,导致数据丢失
在这里插入图片描述
这种方法可以等到线程结束。

多线程的五种状态

在这里插入图片描述

什么是线程安全问题

当多线程同时对同一个全局变量进行写操作时,可能会受到其他线程的干扰,就会产生线程安全问题。导致数据脏读
产生背景:同时,写操作

如何解决线程安全问题

核心思想:在同一时刻,只有一个线程能够进行写操作
加锁的缺点:对程序的效率降低,变成单线程了

Java中如何解决线程安全问题

Lock锁,synchronized,cas无锁机制,手写乐观锁
synchronized如何解决线程安全问题?
在多个线程在同时执行同一方法时,必须要获得锁才能执行。
线程A获得到锁的情况下,那么线程b就会一直阻塞等待,悲观锁,必须等A执行完释放锁,B才能重新进入获得锁的过程,重新竞争
在这里插入图片描述
这样写是不行的,因为线程A如果进入方法,他就会一直卖票,直到卖完,就变成单线程了。因为synchronized会在run方法执行完毕或者程序抛出异常的情况下自动释放锁。
在这里插入图片描述
这样也是不行的,这样会导致最后一张时,A,B都进入了while循环,会导致超卖的问题。
所以要在ticket方法内再加一个count判断就好了。
例如单例中的双重检验锁模式:
在这里插入图片描述

synchronized的使用方式:

1)代码块
1使用synchronized锁的时候可以使用任意对象锁作为锁。
2如果在方法上加上synchronized关键字默认使用this锁。
注意:如果是静态方法,就使用当前类的class字节码作为锁:synchronized(类.class);如果不是静态方法,使用this锁。synchronized(this)
在这里插入图片描述

重入锁

重入锁,悲观锁,乐观锁,自旋锁,cas,非公平锁
基本锁都具有可重入性,
如果锁不具有重入性,可能会发生死锁
synchronized和lock都是具有可重入性的
在这里插入图片描述
因为传递的都是同一把锁,如果不具有可重入性,线程在获得a的锁后还要去尝试获得b的锁,那可能会造成死锁

多线程死锁

产生背景:在同步中嵌套同步,在锁中嵌套锁
同时:
A先获取obj锁,再去获取this锁
B先获取this锁,再去获取obj锁,很明显会出现死锁

如何排查死锁

Java JDK自带多线程死锁检查工具Jconsole

Lock锁与Synchronized锁区别

Synchronized是Java内置关键字,lock是具有aqs(指的是AbstractQueuedSynchronizer,它提供了一种实现阻塞锁和一系列依赖FIFO等待队列的同步器的框架,ReentrantLock、Semaphore、CountDownLatch、CyclicBarrier等并发类均是基于AQS来实现的,)封装的锁。
Synchronize可以理解为自动挡,当程序运行完毕和抛出异常,自动释放锁。
Lock锁是人为控制获取锁和释放锁,扩展性好,实际上是个接口
在这里插入图片描述
这一定要try起来,万一报错,没有及时释放锁
在这里插入图片描述

读写锁

在这里插入图片描述
读是可以同时进行的
在这里插入图片描述
写锁则是排他的,执行结果为
在这里插入图片描述

多线程之间的通信

wait(),notify()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值