Java线程

线程的六种状态:

NEW:新建,还没启动时的状态

RUNNABLE:可运行,正在JVM中执行,但是可能在等待操作系统资源,比如等待CPU调度

BLOCKED:阻塞,可能处于同步代码块或方法中,需要等别的线程退出

WAITING:等待,该线程被调用了wait方法,相当于是被通知等待

TIMED_WAITING:定时等待,具有指定等待时间的等待

TERMINATED:终止,线程正常完成执行或出现异常

 

切换过程:

创建(开始)→可运行(等待锁)

阻塞(拿到锁)→可运行(收到通知等待)

等待(收到通知执行)→可运行(收到带有等待时间的通知)

定时等待(等待超时/收到通知执行)→可运行(正常执行/执行异常)

终止

 

Tip 1:如何正确中止一个线程?

首先不应使用stop(),而应使用interrupt(),因为stop()过于暴力,破坏了原子性。调用interrupt()后,也并不会就允许线程继续运行,但是它可以使被终止的例如sleep()之类可以抛InterruptedException的方法抛出异常,编写程序的时候可以捕获这个异常,并编写相应的处理逻辑,从而使中断变得可控。 

Tip 2:等待和阻塞两种状态有何区别?

生动一点来说的话,等待是本来自己运行得好好的,突然被别人叫住,说暂停手上的活(WAITING)或者等两秒之后再继续(TIMED_WAITING),而阻塞是好比我此时正准备要上厕所(同步代码块),但是发现厕所门锁住了(说明有人在里面),所以我要在门外等待,里面的人出来了,我才可以进去。

 

线程通信

文件共享 - 写进文件,从文件读

变量共享 - 写入变量,从变量读

JDK提供的线程协作API - wait/notify机制,park/unpark机制

 

Tip 1:suspend和resume被弃用的原因?

1.同步代码块中,suspend不会释放锁,容易死锁 2.对调用顺序有要求,由于多个线程的执行先后顺序不受控,会出现resume比suspend先调用的情况,会导致永久等待

Tip 2:wait/notify不会死锁的原因?

wait会使当前线程等待,加入到当前对象的“等待集合”中,并且释放当前持有的对象锁。而notify/notifyAll可以唤醒一个或所有正在等待这个对象锁的线程。

Tip 3:wait/notify和park/unpark的区别?

wait/notify需要注意先后顺序,否则会出现永久等待,而park/unpark是基于令牌的思想,不用担心先后顺序的问题,但是同步代码块中会有死锁的问题

Tip 4:如何避免伪唤醒?

伪唤醒是指虽然代码是判断了条件不符合才进入等待的,但是被唤醒之后并不意味着条件就符合了(可能有无关线程调用了notifyAll),为了避免这种情况,代码尽量写成while(条件){wait()},而不是if(条件){wait()}

 

posted @ 2021-02-09 12:18  聆道  阅读(69)  评论(0编辑  收藏  举报
页脚代码