Java基础
目录
怎么线程通讯
线程状态:
线程在⽣命周期中并不是固定处于某⼀个状态⽽是随着代码的执⾏在不同状态之间切换。Java
线程状 态变迁如下图所示:
线程创建之后它将处于 NEW
(新建) 状态,调⽤ start()
⽅法后开始运⾏,线程这时候处于 READY
(可运⾏) 状态。可运⾏状态的线程获得了 cpu
时间⽚(timeslice)
后就处于 RUNNING
(运 ⾏) 状态。
操作系统隐藏 Java
虚拟机(JVM)
中的 READY
和 RUNNING 状态,它只能看到 RUNNABLE
状态,所以 Java 系统⼀般将这两 个状态统称为 RUNNABLE(运⾏中) 状态 。
当线程执⾏ wait()
⽅法之后,线程进⼊ WAITING
(等待)状态。进⼊等待状态的线程需要依靠其他 线程的通知才能够返回到运⾏状态,⽽ TIME_WAITING
(超时等待) 状态相当于在等待状态的基础上增加 了超时限制,⽐如通过 sleep(long millis)
⽅法或 wait(long millis)
⽅法可以将 Java 线程置于 TIMED WAITING
状态。当超时时间到达后 Java 线程将会返回到 RUNNABLE
状态。当线程调 ⽤同步⽅法时,在没有获取到锁的情况下,线程将会进⼊到 BLOCKED
(阻塞) 状态。线程在执⾏ Runnable
的run()
⽅法之后将会进⼊到 TERMINATED
(终⽌) 状态。
多线程的创建,怎么退出线程,退出进程
多线程
为什么不能用默认的线程池创建
退出线程
关闭线程池:
ThreadPoolExecutor#shutdown
ThreadPoolExecutor#shutdownNow
线程池的参数
同2
线程池的状态
RUNNING
:线程池创建之后的初始状态,这种状态下可以执行任务。SHUTDOWN
:该状态下线程池不再接受新任务,但是会将工作队列中的任务执行结束。STOP
: 该状态下线程池不再接受新任务,但是不会处理工作队列中的任务,并且将会中断线程。TIDYING
:该状态下所有任务都已终止,将会执行 terminated() 钩子方法。TERMINATED
:执行完 terminated() 钩子方法之后。
死锁怎么预防
产⽣死锁必须具备以下四个条件:
- 互斥条件:该资源任意⼀个时刻只由⼀个线程占⽤。
- 请求与保持条件:⼀个进程因请求资源⽽阻塞时,对已获得的资源保持不放。
- 不剥夺条件:线程已获得的资源在末使⽤完之前不能被其他线程强⾏剥夺,只有⾃⼰使⽤完毕后 才释放资源。
- 循环等待条件:若⼲进程之间形成⼀种头尾相接的循环等待资源关系。
如何避免线程死锁?
上⾯说了产⽣死锁的四个必要条件,为了避免死锁,我们只要破坏产⽣死锁的四个条件中的其中⼀个就可以了。现在我们来挨个分析⼀下:
- 破坏互斥条件 :这个条件我们没有办法破坏,因为我们⽤锁本来就是想让他们互斥的(临界资 源需要互斥访问)。
- 破坏请求与保持条件:⼀次性申请所有的资源。
- 破坏不剥夺条件 :占⽤部分资源的线程进⼀步申请其他资源时,如果申请不到,可以主动释放 它占有的资源。
- 破坏循环等待条件 :靠按序申请资源来预防。按某⼀顺序申请资源,释放资源则反序释放。破 坏循环等待条件。
出现了死锁怎么办
检测死锁:
当我们出现死锁的时候,首先需要使用jps命令查看运行的程序
jps -l
jstack 7560 # 后面参数是 jps输出的该类的pid
解除死锁:
发生死锁后,撤销进程,回收资源,分配给正在阻塞状态的进程。
银行家怎么实现
进程调度CFS
时钟调度算法
慢查询优化
ThreadLocal场景应用,spring里有用到吗
来自面试突击pdf
通常情况下,我们创建的变量是可以被任何⼀个线程访问并修改的。如果想实现每⼀个线程都有⾃⼰的 专属本地变量该如何解决呢? JDK中提供的ThreadLocal
类正是为了解决这样的问题。 ThreadLocal
类主要解决的就是让每个线程绑定⾃⼰的值,可以将ThreadLocal
类形象的⽐喻成存 放数据的盒⼦,盒⼦中可以存储每个线程的私有数据。
如果你创建了⼀个ThreadLocal
变量,那么访问这个变量的每个线程都会有这个变量的本地副本,这 也是ThreadLocal
变量名的由来。他们可以使⽤ get()
和 set()
⽅法来获取默认值或将其 值更改为当前线程所存的副本的值,从⽽避免了线程安全问题。
Java中各种锁聊一下,CAS机制
读写锁:
private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
// 创建一个写锁
rwLock.writeLock().lock();
// 写锁 释放
rwLock.writeLock().unlock();
// 创建一个读锁
rwLock.readLock().lock();
// 读锁 释放
rwLock.readLock().unlock();
公平锁/非公平锁
/**
* 创建一个可重入锁,true 表示公平锁,false 表示非公平锁。默认非公平锁
*/
Lock lock = new ReentrantLock(true);
可重入锁和递归锁ReentrantLock
自旋锁
自旋锁:spinlock
,是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗CPU
原来提到的比较并交换(CAS),底层使用的就是自旋,自旋就是多次尝试,多次访问,不会阻塞的状态就是自旋。
自旋锁
CAS
CAS的全称是Compare-And-Swap
,它是CPU并发原语
它的功能是判断内存某个位置的值是否为预期值,如果是则更改为新的值,这个过程是原子的.
CAS
volatile有用过么,底层实现
Volatile在日常的单线程环境 是应用不到的
Volatile是Java虚拟机提供的轻量级的同步机制(三大特性):
- 保证可见性
- 不保证原子性
- 禁止指令重排
Runnable和Collable的定义和区别
上一篇: 实习面试试题及答案
下一篇: Centos7.6安装Docker