日常记录——多线程与高并发—线程状态、方法以及对象的锁池、等待池

一.Java中的线程的生命周期

线程的状态转换是线程控制的基础。线程状态总的可分为五大状态:创建(NEW)、就绪(RUNNABLE)、运行(RUNNING)、阻塞(BLOCKED)、结束(DEAD)。
具体展现为:
1.创建(NEW):新创建了一个线程对象,并没有调用start()方法之前。
2.就绪(RUNNABLE):当start()方法调用后,线程有资格运行,但还未获取到cpu资源时。线程首先进入.就绪状态。在线程运行之后从阻塞状态回来后,也返回到就绪状态。、
3. 运行(RUNNING):就绪状态线程获得了cpu 资源,执行代码逻辑。
4. 阻塞(BLOCKED):阻塞状态是指线程因为某种原因放弃了cpu资源,暂时停止运行,直到线程进入可运行(runnable)状态。比如:调用sleep(),另一个线程插队t2.join(),遇到了wait()。
5. 结束(DEAD):线程方法执行结束,结束不可重新调用start(),会抛出java.lang.IllegalThreadStateException异常。

二、线程状态流程图

在这里插入图片描述

三、对象的锁池、等待池

在java中,每个对象都有两个池,锁池和等待池,每个对象都有且只有一个锁

锁池:假设线程A已经拥有了某个对象的锁,而其它的线程想要调用这个对象的某个synchronized方法或synchronized块,由于这些线程在进入对象的synchronized方法之前必须先获得该对象的锁的拥有权,但是该对象的锁目前正被线程A拥有,所以这些线程就进入了该对象的锁池中。

等待池:假设一个线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁后,进入到了该对象的等待池中,等待池中的线程不会去竞争该对象的锁,当该对象的notify()或notifyAll()执行,则将会将等待池中的一条或者全部唤醒,放到锁池中去竞争对象锁。

四、相关方法

(1).Thread类

1.currentThread()
返回的当前正在执行线程对象的引用
2.setName(String name) getName()  
设置和获取线程名称。
3.setPriority(int newPriority) getPriority()  
设置和获取线程的优先级。优先级高的线程得到的cpu资源几率大。只是几率大,不是必定。默认情况下,线程的优先级是5。线程的优先级分为1~10等级。
4.boolean isDaemon()   
测试该线程是否为守护线程。
5.setDaemon(boolean on)  
将该线程标记为守护线程或用户线程,当系统中无用户线程,守护线程自动退出,守护线程如:gc线程。
6.void run()  
调用后执行run方法体,普通方法,无线程启动
7.void start()  
调用后线程进入就绪状态
8.sleep()
释放cpu资源,进入阻塞状态,不释放锁资源,如果线程进入sleep的话,释放cpu资源,如果外层包有Synchronize,那么此锁并没有释放掉。
9.yield()
当前线程调用此方法,当前线程放弃获取的cpu资源,不会导致阻塞,由运行状态变回就绪状态,重新竞争cpu资源。作用:让相同优先级的线程轮流执行,但并不保证一定会轮流执行。实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。
10.t2.join()/t2.join(long millis)
当前线程里调用其它线程t2的join方法,当前线程阻塞,但不释放t1线程的对象锁,释放t2这个线程对象的锁,线程(t1) 释放掉 线程(t2.join中的t2)这把锁,直到线程t1执行完毕或者millis时间到,当前线程进入可运行状态。
11.interrupt()
作用是中断此线程(此线程不一定是当前线程,而是指调用该方法的Thread实例所代表的线程),但实际上只是给线程设置一个中断标志,线程仍会继续运行,并不能真正的中断线程,需要被调用的线程自己进行配合才可以中断。

Thread thread = new Thread(() -> {
    while (!Thread.interrupted()) {
        // do more work.
    }
});

如果线程处于被阻塞状态(例如处于sleep, wait, join 等状态),那么线程将立即退出被阻塞状态,并抛出一个InterruptedException异常。
12.interrupted()
当前线程是否被中断(检查中断标志),返回一个boolean并清除中断状态
13.isInterrupted()
当前线程是否被中断 ,不清除中断状态。

(2).Object超类

1.wait()
使当前线程暂停执行,让出CPU资源并释放对象锁,让其他线程可以进入Synchronized数据块,当前线程被放入对象等待池中。
2.notify()
将从对象的等待池中移走一个任意的线程并放到锁池中,只有锁池中的线程能够获取对象锁资源;如果锁池中没有线程,则notify()不起作用。
3.notifyAll()
从对象等待池中移走所有等待那个对象的线程并放到锁池中。
注意:wait()、notify()、notifyAll() 必须在同步代码块中 否则会IllegalMonitorStateException异常
wait()就是释放锁,释放锁的前提是必须要先获得锁,先获得锁才能释放锁
notify(),notifyAll()是将锁交给含有wait()方法的线程,让其继续执行下去,如果自身没有锁,怎么把锁交给其他线程;

猜你喜欢

转载自blog.csdn.net/weixin_43001336/article/details/106963188