当前位置: 首页>移动开发>正文

Java基础面试题突击系列4

?? 《java面试核心知识突击系列》,持续更新...
?? 作者:一只IT攻城狮
?? 再小的收获x365天都会成就不一样的自己,一起学习,一起进步。

一、守护线程(服务线程)

守护线程是后台线程,为用户线程提供公共服务。任何线程都可以设置为守护线程和用户线程,通过方法Thread.setDaemon(bool on);true则把该线程设置为守护线程,反之则为用户线程。Thread.setDaemon()必须在Thread.start()之前调用,否则运行时会抛出异常。

守护线程优先级较低是jvm级别的,垃圾回收就是一个经典的守护线程,当垃圾回收线程是jvm仅剩的线程时,会自动离开,jvm就可以退出了,守护线程不依赖终端,与系统“同生共死”。Finalizer也是守护线程。

二、红黑树有哪几个特征?

1、每个节点是 黑色或红色
2、根节点是黑色
3、每个叶子节点都是黑色(指向空的叶子节点)
4、如果一个叶子节点是红色,那么其子节点必须都是黑色的
5、从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点

Java基础面试题突击系列4,第1张

三、线程的 run() 和 start() 有什么区别和关系?

调用start方法方可启动线程,源码分析里面调用了start0,是一个native方法,start() 只能调用一次;非java实现的,这个方法里面实现了多线程并对run方法进行了调用。

而run方法用于执行线程的运行时代码,只是thread类中的一个普通方法调用,还是在主线程里执行,run() 可以重复调用。所以直接调用run,就像普通实例对象调用自己的普通方法一样,只会顺序执行!
在start这个方法的设计上,其实java源码采用了“模版模式”这种设计模式。所以一定要调用start启动线程。

四、多线程的上下文切换

1、上下文

上下文:是指某一时间点,cpu寄存器(cpu内部数量较小但是速度很快的内存)和程序计数器(表明cpu执行的位置)内容;上下文切换是内核(操作系统核心)在cpu上对进程(线程)的切换,切换过程中的信息是保存在进行控制块PCB中的,PCB还被称作“切换帧”,信息一致保存在cpu内存中,知道被再次使用。

多线程的上下文切换即任务状态的保存再加载(因为cpu时间片轮转,所以就会切换)

2、上下文切换的内容

上下文切换的内容:挂起一个进程,将这个进程在cpu中状态(上下文)存储于内存中某处;
在内存中检索下一个进程的上下文,并将其在cpu寄存器恢复;
跳到程序计数器指向的位置,恢复该进程;

五、get方式和post方式有何区别

GET方式:在URL地址后附带的参数是有限制的,其数据容量通常不能超过1K。请求参数放在URL地址后面,以?的方式来进行拼接;GET方式一般用来获取数据。

POST方式:可以在请求的实体内容中向服务器发送数据,传送的数据量无限制。请求参数放在HTTP请求包中;POST方式一般用来提交数据。

六、Java中用到的线程调度算法

1、调度

抢占式调度:线程切换由系统控制(一个线程阻塞不会导致整个进程阻塞);
协助式调度(接力):由线程本身控制(一个线程阻塞,整个系统奔溃);
jvm中线程调度是抢占式调度;

java中线程调度是时间片轮转的方式;可以设置线程的优先级,按照优先级分配时间片,但是尽量不要用,防止线程饥饿。

2、算法

1)优先调度算法:
先来先服务调度算法;
短作业优先调度算法;

2)高优先权优先调度算法:
非抢占式优先权调度算法;
抢占式优先权调度算法;
高响应比优先调度算法;

小结:每一个线程都是有优先级的,一般来说,高优先级的线程在运行时会具有优先权,但这依赖于线程调度的实现,这个实现是和操作系统相关的(OS dependent)。我们可以定义线程的优先级,但是这并不能保证高优先级的线程会在低优先级的线程前执行。线程优先级是一个int变量(从1-10),1代表最低优先级,10代表最高优先级。

七、创建线程有哪几种方式?

1、继承 Thread 重写 run 方法;
2、实现 Runnable 接口;
3、实现 Callable 接口;
4、通过线程池创建。

更详细介绍:java中如何创建一个线程?

八、线程有哪些状态?

1、New(初始化状态)
用new语句创建的线程处于新建状态,此时它和其他Java对象一样,仅仅在堆区中被分配了内存。如:Thread t = new MyThread();

2、Runnable(就绪状态)
当调用线程对象的start()方法,线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,Java虚拟机会为它创建方法调用栈和程序计数器。处于这个状态的线程位于可运行池中,等待获得CPU的使用权,并不是说执行了start()此线程立即就会执行。

3、Running(运行状态)
当就绪状态中的线程获得了CUP执行资源,执行run()中的代码,这样的线程我们称为运行状态的线程。

4、Blocked(阻塞状态)
处于运行中的线程,由于某种原因放弃对cpu的使用权,处于阻塞状态,直到其进入就绪状态,才有机会再次被cpu调用进入运行状态。

5、Terminated(终止状态)

更详细介绍:线程生命周期及五种状态

九、线程池都有哪些状态?

线程池生命周期的五种状态:
1、RUNNING:这是最正常的状态,接受新的任务,处理等待队列中的任务。

2、SHUTDOWN:不接受新的任务提交,但是会继续处理等待队列中的任务。

3、STOP:不接受新的任务提交,不再处理等待队列中的任务,中断正在执行任务的线程。

4、TIDYING:所有的任务都销毁了,workCount 为 0,线程池的状态在转换为 TIDYING 状态时,会执行钩子方法 terminated()。

5、TERMINATED:terminated()方法结束后,线程池的状态就会变成这个。

更详细介绍:Java多线程之Executor框架

十、线程池实现原理

1、如果运行线程数小于corePoolSize,那么马上创建线程运行这个任务;

2、如果正在运行的线程数大于等于corePoolSize,那么将这个任务放进队列;

3、如果队列放满了,如果正在运行的线程数小于maximumPoolSize,创建线程处理任务;

4、如果队列放满了,正在运行的线程数大于等于maximumPoolSize,那么线程会抛出异常;RejectExecutionException,执行拒绝策略。

十一、线程池4种拒绝策略

1、AbortPolicy :直接抛出异常,阻止系统运行(线程池默认的拒绝策略);

2、CallerRunsPolicy:由调用线程处理;

3、DiscardPolicy:丢弃无法处理的任务,不予任何处理;

4、DiscardOldestPolicy:丢弃最老的一个请求,也就是即将被执行的一个任务,重新提交被拒绝的任务。

十二、Java中CycliBarriar和CountdownLatch的区别

CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点不同:

CountDownLatch一般用于某个线程A等待若干个其他线程执行完任务之后,它才执行;
而CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行;
另外,CountDownLatch是不能够重用的,而CyclicBarrier是可以重用的。

十三、怎么检测一个线程是否拥有锁

在java.lang.Thread中有一个方法叫holdsLock(),它返回true如果当且仅当当前线程拥有某个具体对象的锁。

十四、不可变对象

Java平台类库中包含许多不可变类,如String、基本类型的包装类、BigInteger和BigDecimal等。它们的常量(域)是在构造函数中创建的。既然它们的状态无法修改,这些常量永远不会变。

不可变对象永远是线程安全的。
只有满足如下状态,一个对象才是不可变的;
它的状态不能在创建后再被修改;
所有域都是final类型;并且它被正确创建(创建期间没有发生this引用的逸出)。

十五、线程池中 submit() 和 execute() 方法有什么区别?

execute():只能执行 Runnable 类型的任务。
submit():可以执行 Runnable 和 Callable 类型的任务。


Java基础面试题突击系列4,第2张

https://www.xamrdz.com/mobile/4mh1994684.html

相关文章: