发下Tree底层都是使用了红黑二叉树来进行排序。红黑二叉树是一种特殊的平衡二叉树。平衡二叉树是1空树、2,左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一颗平衡二叉树。详情参考大神的https://www.cnblogs.com/guweiwei/p/7080971.html
26.线程实现的方式
创建线程只有一种方法,构造Thread类,但实现线程的执行单元有两种方法
1.重写Thread的run方法
2.实现Runnable接口的run方法,并且将Runnable实例用作构造Thread参数
27.如何停止一个线程
1.创建一个标识(flag),当线程完成你所需要的工作后,可以将标识设置为退出标识
2.使用Thread的stop()方法,这种方法可以强行停止线程,不过已经过期了,因为其在停止的时候可能会导致数据的紊乱
3.使用Thread的interrupt()方法和Thread的interrupted()方法,两者配合break退出循环,或者return来停止线程,有点类似标识(flag)
4.(推荐)当我们想要停止线程的时候,可以使用try-catch语句,在try-catch语句中抛出异常,强行停止线程进入catch语句,这种方法可以将错误向上抛,使线程停止事件得以传播
running-->锁池
- 调用wait()方法后进入等待队列,后又被notify()/notifyAll()唤醒,进入锁池
- 对象直接被synchronized,进入锁池
Runningàrunnable
- CPU时间片用完
- 线程调用yield()方法Thread.yield()
- 进入堵塞(等待用户输入、线程调用Sleep()方法、线程调用join()方法)状态,堵塞结束(用户输入完成,sleep()、join()时间到)
28.如何保证线程安全
对非安全的代码进行加锁操作、使用线程安全的类、不要跨线程访问共享变量、使用final类型作为共享变量、对共享变量加锁操作
29.Synchronized和Lock的区别
相同点:Lock能完成Synchronized所实现的所有功能
不同点:
Synchronized是基于JVM的同步锁,JVM会帮我们自动释放锁。Lock是通过代码实现的,Lock要求我们手工释放,必须在finally语句中释放。
Lock锁的范围有局限性、块范围。Synchronized可以锁块、对象、类
Lock功能比Synchronized强大,可以通过tryLock方法在非阻塞线程的情况下拿到锁
31.多线程中的死锁
死锁:指两个或两个以上的线程在执行的过程中,因抢夺资源而造成互相等待,导致线程无法进行下去
产生死锁的4个必要条件
循环等待:线程中必须有循环等待
不可剥夺:线程已获得资源,再未使用完成之前,不可被剥夺抢占
资源独占:线程在某一时间内独占资源
申请保持:线程因申请资源而阻塞,对已获得的资源保持不放
32.Java中的BIO,NIO,AIO分别是什么,应用场景是什么
简单理解堵塞和非堵塞
堵塞:cpu停下来等待一个慢的操作完成,cpu才接着完成其他的工作
非堵塞:在这个慢的操作执行的过程中,cpu去干别的事情,等待慢动作完成,cpu再回来
BIO:同步并阻塞,服务器实现模式是一个连接对应一个线程,即客户端有连接请求时,服务器就会开启一个线程进行处理,如果这个连接不做任何事情时,会造成不必要的线程开销,可以使用线程池进行改善。其应用场景适用于连接数目比较小且固定的架构,这种方式对服务器资源要求较高,对线程并发有局限性
NIO:同步非阻塞,服务器实现模式是一个请求对应一个线程,即客户端的连接请求都会注册在多路复用器上,当多路复用器轮询到有I/O请求时才启动一个线程进行处理。其应用场景适用于连接数目多且连接短的架构,对线程并发有局限性
AIO:异步非阻塞,服务器实现模式是一个有效请求对应一个线程,即客户端的I/O请求完成之后,再通知服务器去启动一个线程进行处理。其应用场景适用于连接数目多且连接长的架构,充分体现出并发性
33.Java中的IO和NIO的区别
- IO是面向流的,NIO是面向缓冲区的
- IO的各种流是阻塞的,NIO是非阻塞模式
34.volatile关键字
用volatile修饰的变量,线程在每次修改变量的时候,都会读取变量修改后的值,可以简单的理解为volatile修饰的变量保存的是变量的地址。volatile变量具有synchronized的可见性,,但是不具备原子性
可见性:在多线程并发的条件下,对于变量的修改,其他线程中能获取到修改后的值 synchronized的可见性是由“对一个变量执行unlock操作之前,必须先把此变量同步回主内存中 final关键字的可见性是由于在构造器中一旦完成初始化操作,那么在其他线程中就能看见final字段的值。
原子性:在多线程并发的条件下,对于变量的操作是线程安全的,不会受到其他线程的干扰
volatile不是线程安全的,要使volatile变量提供理想的线程安全,必须同时满足下面两个条件
对变量的写操作不依赖于当前值
该变量没有包含在具有其他变量的不变式中
Java提供了java.util.concurrent.atomic.*
包下的变量或引用,让变量或对象的操作具有原子性,在高并发的情况下,依然能保持获取到最新修改的值,常见的有AtomicBoolean、AtomicReference等
- volatile原理:对于值的操作,会立即更新到主存中,当其他线程获取最新值时会从主存中获取
- atomic原理:对于值的操作,是基于底层硬件处理器提供的原子指令,保证并发时线程的安全