Java-多线程并发01并发基础知识
线程的声明周期及其状态:
实现线程的三种方式:
1.继承Thread重写Run方法。
start方法调用后,线程处于就绪态,执行run方法,执行完毕后处于终止态。
优点:获取线程直接在Run里边this。 不需要Thread.currentThread()。
缺点:不支持多继承,任务和代码没有分离,多个线程执行相同任务需要多份代码。如果运行第二遍start会报错ill'egalThreadStateException
2.Runable接口实现
优点:多个线程共用一个task代码逻辑。如果由需要可以加参数区分。同时实现了Runable接口的还可以继承其他的类。
缺点: 和Runnable一样,没有return返回值。
3.FutureTask:
首先创建一个静态类继承Callable接口,并覆盖他的cal方法。
在main函数中,首先创建一个FutureTask对象,并在他的构造器中把实现Callable接口的对象传进去。
然后创建一个FutureTask对象作为线程并启动他,最后可以通过get方法等待任务执行完毕并获取返回值。(这里get方法需要抛一个运行异常因为需要等待他的结果)
Waits if necessary for the computation to complete, and then retrieves its result.
必要时等待计算完成,然后检索其结果。
三种方式的优缺点:
Thread:方便传参数,可以在子类里面添加变量,通过set方法设置参数或者通过构造器进行传递。 由于这个是继承,所以不能再去继承其他的类。
Runable:只能使用主线程的final变量。
Future:可以拿到返回结果
wait(): 调用的线程被阻塞挂起。需要实现获得监视器锁
唤醒的条件:
1).其他线程调用了该共享对象的notify()、notifyAll()
2).其他线程调用了该线程的interrupt(),该线程抛出InterruptException异常返回。
如果调用wait()方法的线程没有实现获取该对象的监视器锁,则会抛出illegalMointorStateException异常。
如何获取共享变量的监视器锁?
执行Synchronized同步代码块时,使用该共享变量作为参数。
调用该共享变量的方法,并且该方法使用Synchronized修饰。
简单来说,就是执行Synchronized代码块时把共享变量作为参数,然后再去执行共享变量的方法,就会获得共享变量的监视器锁。
对于锁和监视器的理解:https://www.cnblogs.com/keeplearnning/p/7020287.html
锁:
监视器:java中的每个对象都有一个内部锁和内部条件。如果一个方法用synchronized关键字声明,那么,它表现的就像一个监视器方法。通过wait/notifyAll/nofify来访问条件变量
虚假唤醒:
一个线程有可能会不通过正常的方法(notify,中断,等待超时)被从挂起状态变成可运行状态。
所以需要利用条件循环去不断的让他处于挂起状态。
while(条件不满足){
obj.wait();
}
特性:当线程调用共享变量的wait()方法后只会释放共享变量上的锁,如果共享变量在的这个线程还有其他共享变量的锁,对其他共享变量的锁不负责。
如果在使用wati阻塞挂起的过程中被其他线程调用interrupt中断,会抛出InterruptException异常。
wait(long timeout):如果在timeout时间内没有被唤醒,会因超时返回。 timeout的值为负会报错。
wait(long timeout,int nanos):内部调用wait(long timeout),nanos>0时 timeout++
notify:
随机唤醒一个共享变量调用wait挂起的线程。被唤醒的线程不会立马获得共享对象的监视器锁,仍需要和其他的线程一起竞争该锁。
只有当前的线程获得了监视器锁,才可以调用共享变量的notify方法。
notifyAll:
唤醒所有被wait挂起的线程。
例子:
线程A{
synchronized(A)
A.wait
}
线程B{
synchronized(A)
A.wait
}
线程C{
synchronized(A)
A.notify
}
调用顺序。 A,B 然后等1s 允许C的notify
结果:
线程A拿到共享变量A资源的锁,挂起并释放A资源的锁
线程B拿到共享变量A资源的锁,挂起并释放A资源的锁
此时A,B都在资源A的阻塞队列
这时线程C拿到共享变量A资源的锁,进行唤醒操作,唤醒资源A的阻塞队列中的随机一个线程
线程A被唤醒,结束挂起,从wait方法返回。执行wait后面的语句。
需要注意,唤醒操作是唤醒在调用notify之前进行wait操作的线程。如果在notify之后调用的wait方法不会唤醒。
wait被唤醒后从被挂起地方继续执行下去
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!