没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
1. 并行和并发有什么区别?
� 并行:多个处理器或多核处理器同时处理多个任务。
� 并发:多个任务在同一个 CPU 核上,按细分的时间片轮流(交替)执行,从逻辑上来看那些
任务是同时执行。
2. 线程和进程的区别?
一个程序下至少有一个进程,一个进程下至少有一个线程,一个进程下也可以有多个线程来增加程序
的执行速度。
3. 守护线程是什么?
守护线程是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某
些发生的事件。在 Java 中垃圾回收线程就是特殊的守护线程。
4. 创建线程有哪几种方式?
创建线程有三种方式:
� 继承 Thread 重写 run 方法;
� 实现 Runnable 接口;
� 实现 Callable 接口。
5. 说一下 runnable 和 callable 有什么区别?
runnable 没有返回值,callable 可以拿到有返回值,callable 可以看作是 runnable 的补充。
6. 线程有哪些状态?
线程的状态:
� NEW 尚未启动
� RUNNABLE 正在执行中
� BLOCKED 阻塞的(被同步锁或者 IO 锁阻塞)
� WAITING 永久等待状态
� TIMED_WAITING 等待指定的时间重新被唤醒的状态
� TERMINATED 执行完成
7. sleep() 和 wait() 有什么区别?
类的不同:sleep() 来自 Thread,wait() 来自 Object。
释放锁:sleep() 不释放锁;wait() 释放锁。
用法不同:sleep() 时间到会自动恢复;wait() 可以使用 notify()/notifyAll()直接唤醒。
8. notify()和 notifyAll()有什么区别?
notifyAll()会唤醒所有的线程,notify()只唤醒一个线程。notifyAll() 调用后,会将全部线程由等待池移
到锁池,然后参与锁的竞争,竞争成功则继续执行,如果不成功则留在锁池等待锁被释放后再次参与
竞争。而 notify()只会唤醒一个线程,具体唤醒哪一个线程由虚拟机控制。
9. 线程的 run() 和 start() 有什么区别?
start() 方法用于启动线程,run() 方法用于执行线程的运行时代码。run() 可以重复调用,而 start()
只能调用一次。
start()方法来启动一个线程,真正实现了多线程运行。调用 start()方法无需等待 run 方法体代码执行
完毕,可以直接继续执行其他的代码; 此时线程是处于就绪状态,并没有运行。 然后通过此 Thread
类调用方法 run()来完成其运行状态, run()方法运行结束, 此线程终止。然后 CPU 再调度其它线程。
run()方法是在本线程里的,只是线程里的一个函数,而不是多线程的。 如果直接调用 run(),其实就
相当于是调用了一个普通函数而已,直接待用 run()方法必须等待 run()方法执行完毕才能执行下面的
代码,所以执行路径还是只有一条,根本就没有线程的特征,所以在多线程执行时要使用 start()方法
而不是 run()方法。
10、为什么我们调用 start() 方法时会执行 run() 方法,为什么我们不能直接调用 run()
方法?
这是另一个非常经典的 java 多线程面试问题,而且在面试中会经常被问到。很简单,但是很多人都
会答不上来!
new 一个 Thread,线程进入了新建状态。调用 start() 方法,会启动一个线程并使线程进入了就绪
状态,当分配到时间片后就可以开始运行了。 start() 会执行线程的相应准备工作,然后自动执行 run()
方法的内容,这是真正的多线程工作。
而直接执行 run() 方法,会把 run 方法当成一个 main 线程下的普通方法去执行,并不会在某个线
程中执行它,所以这并不是多线程工作。
总结: 调用 start 方法方可启动线程并使线程进入就绪状态,而 run 方法只是 thread 的一个普通
方法调用,还是在主线程里执行。
11、线程池中的线程是怎么创建的?是一开始就随着线程池的启动创建好的吗?
线程池中的线程是在第一次提交任务 submit 时创建的
创建线程的方式有继承 Thread 和实现 Runnable,重写 run 方法,start 开始执行,wait 等待,sleep
休眠,shutdown 停止。
(1)newSingleThreadExecutor:单线程池。
顾名思义就是一个池中只有一个线程在运行,该线程永不超时,而且由于是一个线程,当有多个任务
需要处理时,会将它们放置到一个无界阻塞队列中逐个处理
(2)newCachedThreadPool:缓冲功能的线程。
建立了一个线程池,而且线程数量是没有限制的(当然,不能超过 Integer 的最大值),新增一个任务
即有一个线程处理,或者复用之前空闲的线程,或者重亲启动一个线程,但是一旦一个线程在 60 秒
内一直处于等待状态时(也就是一分钟无事可做),则会被终止.
(3)newFixedThreadPool:固定线程数量的线程池。
在初始化时已经决定了线程的最大数量,若任务添加的能力超出了线程的处理能力,则建立阻塞队列
容纳多余的任务
以上三种线程池执行器都是 ThreadPoolExecutor 的简化版,目的是帮助开发人员屏蔽获得线程细节,
简化多线程开发。当需要运行异步任务时,可以直接通过 Executors 获得一个线程池,然后运行任务,
不需要关注 ThreadPoolExecutor 的一系列参数时什么含义。当然,有时候这三个线程不能满足要求,
此时则可以直接操作 ThreadPoolExecutor 来实现复杂的多线程计算。
newSingleThreadExecutor、newCachedThreadPool、newFixedThreadPool 是线程池的简化版,而
ThreadPoolExecutor 则是旗舰版___简化版容易操作,需要了解的知识相对少些,方便使用,而旗舰
版功能齐全,适用面广,难以驾驭。
12. 线程池都有哪些状态?
RUNNING:这是最正常的状态,接受新的任务,处理等待队列中的任务。
SHUTDOWN:不接受新的任务提交,但是会继续处理等待队列中的任务。
STOP:不接受新的任务提交,不再处理等待队列中的任务,中断正在执行任务的线程。
TIDYING:所有的任务都销毁了,workCount 为 0,线程池的状态在转换为 TIDYING 状态时,会
执行钩子方法 terminated()。
TERMINATED:terminated()方法结束后,线程池的状态就会变成这个。
13. 线程池中 submit() 和 execute() 方法有什么区别?
execute():只能执行 Runnable 类型的任务。
submit():可以执行 Runnable 和 Callable 类型的任务。
Callable 类型的任务可以获取执行的返回值,而 Runnable 执行无返回值。
14. 在 Java 程序中怎么保证多线程的运行安全?
� 方法一:使用安全类,比如 Java. util. concurrent 下的类。
� 方法二:使用自动锁 synchronized。
� 方法三:使用手动锁 Lock。
15. 多线程中 synchronized 锁升级的原理是什么?
synchronized 锁升级原理:在锁对象的对象头里面有一个 threadid 字段,在第一次访问的时候
threadid 为空,jvm 让其持有偏向锁,并将 threadid 设置为其线程 id,再次进入的时候会先判断
threadid 是否与其线程 id 一致,如果一致则可以直接使用此对象,如果不一致,则升级偏向锁为轻
量级锁,通过自旋循环一定次数来获取锁,执行一定次数之后,如果还没有正常获取到要使用的对象,
此时就会把锁从轻量级升级为重量级锁,此过程就构成了 synchronized 锁的升级。
锁的升级的目的:锁升级是为了减低了锁带来的性能消耗。在 Java 6 之后优化 synchronized 的实
现方式,使用了偏向锁升级为轻量级锁再升级到重量级锁的方式,从而减低了锁带来的性能消耗。
16. 什么是死锁?
当线程 A 持有独占锁 a,并尝试去获取独占锁 b 的同时,线程 B 持有独占锁 b,并尝试获取独占
锁 a 的情况下,就会发生 AB 两个线程由于互相持有对方需要的锁,而发生的阻塞现象,我们称为
死锁。
17 怎么防止死锁?
手工锁(ReentrantLock、ReentrantReadWriteLock)尽量使用 tryLock(long timeout, TimeUnit unit)的
方法,设置超时时间,超时可以退出防止死锁。
尽量使用 Java. util. concurrent 并发类代替自己手写锁。
尽量降低锁的使用粒度,尽量不要几个功能用同一把锁。
尽量减少同步的代码块。
18. ThreadLocal 是什么?有哪些使用场景?
剩余15页未读,继续阅读
资源评论
roseandwar
- 粉丝: 2
- 资源: 37
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功