版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
文档来源网络侵权联系删除PAGEPAGE1仅供参考为什么需要线程+面试题线程介绍线程(Thread)是程序运行的执行单元,依托于进程存在。一个进程中可以包含多个线程,多线程可以共享一块内存空间和一组系统资源,因此线程之间的切换更加节省资源、更加轻量化,因而也被称为轻量级的进程。什么是进程进程(Processes)是程序的一次动态执行,是系统进行资源分配和调度的基本单位,是操作系统运行的基础,通常每一个进程都拥有自己独立的内存空间和系统资源。简单来说,进程可以被当做是一个正在运行的程序。为什么需要线程程序的运行必须依靠进程,进程的实际执行单元就是线程。为什么需要多线程多线程可以提高程序的执行性能。例如,有个90平方的房子,一个人打扫需要花费30分钟,三个人打扫就只需要10分钟,这三个人就是程序中的“多线程”。线程使用线程的创建,分为以下三种方式:继承Thread类,重写run方法实现Runnable接口,实现run方法实现Callable接口,实现call方法下面分别来看看线程创建和使用的具体代码。1)继承Thread类请参考以下代码:classThreadTest{
publicstaticvoidmain(String[]args)throwsException{
MyThreadthread=newMyThread();
thread.start();
}
}
classMyThreadextendsThread{
@Override
publicvoidrun(){
System.out.println("Thread");
}
}以上程序执行结果如下:Thread2)实现Runnable接口请参考以下代码:classThreadTest{
publicstaticvoidmain(String[]args){
MyRunnablerunnable=newMyRunnable();
newThread(runnable).start();
}
}
classMyRunnableimplementsRunnable{
@Override
publicvoidrun(){
System.out.println("Runnable");
}
}以上程序执行结果如下:Runnable3)实现Callable接口请参考以下代码:classThreadTest{
publicstaticvoidmain(String[]args)throwsException{
MyCallablecallable=newMyCallable();
//定义返回结果
FutureTask<String>result=newFutureTask(callable);
//执行程序
newThread(result).start();
//输出返回结果
System.out.println(result.get());
}
}
classMyCallableimplementsCallable{
@Override
publicStringcall(){
System.out.println("Callable");
return"Success";
}
}以上程序执行结果如下:CallableSuccess可以看出,Callable的调用是可以有返回值的,它弥补了之前调用线程没有返回值的情况,它是随着JDK1.5一起发布的。4)JDK8创建线程JDK8之后可以使用Lambda表达式很方便地创建线程,请参考以下代码:newThread(()->System.out.println("LambdaOfThread.")).start();线程高级用法线程等待使用wait()方法实现线程等待,代码如下:System.out.println(LocalDateTime.now());
Objectlock=newObject();
Threadthread=newThread(()->{
synchronized(lock){
try{
//1秒钟之后自动唤醒
lock.wait(1000);
System.out.println(LocalDateTime.now());
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
});
thread.start();以上程序执行结果如下:2019-06-22T20:53:08.7762019-06-22T20:53:09.788注意:当使用wait()方法时,必须先持有当前对象的锁,否则会抛出异常java.lang.IllegalMonitorStateException。线程唤醒使用notify()/notifyAll()方法唤醒线程。notify()方法随机唤醒对象的等待池中的一个线程;notifyAll()唤醒对象的等待池中的所有线程。使用如下:Objectlock=newObject();
lock.wait();
lock.notify();
//lock.notifyAll();线程休眠//休眠1秒
Thread.sleep(1000);等待线程执行完成ThreadjoinThread=newThread(()->{
try{
System.out.println("执行前");
Thread.sleep(1000);
System.out.println("执行后");
}catch(InterruptedExceptione){
e.printStackTrace();
}
});
joinThread.start();
joinThread.join();
System.out.println("主程序");以上程序执行结果:执行前执行后主程序yield交出CPU执行权newThread(){
@Override
publicvoidrun(){
for(inti=1;i<10;i++){
if(i==5){
//让同优先级的线程有执行的机会
this.yield();
}
}
}
}.start();注意:yield方法是让同优先级的线程有执行的机会,但不能保证自己会从正在运行的状态迅速转换到可运行的状态。线程中断使用System.exit(0)可以让整个程序退出;要中断单个线程,可配合interrupt()对线程进行“中断”。
使用代码如下:ThreadinterruptThread=newThread(){
@Override
publicvoidrun(){
for(inti=0;i<Integer.MAX_VALUE;i++){
System.out.println("i:"+i);
if(this.isInterrupted()){
break;
}
}
}
};
interruptThread.start();
Thread.sleep(10);
interruptTerrupt();线程优先级在Java语言中,每一个线程有一个优先级,默认情况下,一个线程继承它父类的优先级。可以使用setPriority方法设置(1-10)优先级,默认的优先级是5,数字越大表示优先级越高,优先级越高的线程可能优先被执行的概率就越大。
设置优先级的代码如下:Threadthread=newThread(()->System.out.println("Java"));
thread.setPriority(10);
thread.start();死锁死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。
比如,当线程A持有独占锁a,并尝试去获取独占锁b的同时,线程B持有独占锁b,并尝试获取独占锁a的情况下,就会发生AB两个线程由于互相持有对方需要的锁,而发生的阻塞现象,我们称为死锁。
死锁示意图如下所示:
死锁代码:Objectobj1=newObject();
Objectobj2=newObject();
//线程1拥有对象1,想要等待获取对象2
newThread(){
@Override
publicvoidrun(){
synchronized(obj1){
try{
Thread.sleep(1000);
}catch(InterruptedExceptione){
e.printStackTrace();
}
synchronized(obj2){
System.out.println(Thread.currentThread().getName());
}
}
}
}.start();
//线程2拥有对象2,想要等待获取对象1
newThread(){
@Override
publicvoidrun(){
synchronized(obj2){
try{
Thread.sleep(1000);
}catch(InterruptedExceptione){
e.printStackTrace();
}
synchronized(obj1){
System.out.println(Thread.currentThread().getName());
}
}
}
}.start();相关面试题1.线程和进程有什么区别和联系?答:从本质上来说,线程是进程的实际执行单元,一个程序至少有一个进程,一个进程至少有一个线程,它们的区别主要体现在以下几个方面:进程间是独立的,不能共享内存空间和上下文,而线程可以;进程是程序的一次执行,线程是进程中执行的一段程序片段;线程占用的资源比进程少。2.如何保证一个线程执行完再执行第二个线程?答:使用join()方法,等待上一个线程的执行完之后,再执行当前线程。
示例代码:ThreadjoinThread=newThread(()->{
try{
System.out.println("执行前");
Thread.sleep(1000);
System.out.println("执行后");
}catch(InterruptedExceptione){
e.printStackTrace();
}
});
joinThread.start();
joinThread.join();
System.out.println("主程序");3.线程有哪些常用的方法?答:线程的常用方法如下:currentThread():返回当前正在执行的线程引用getName():返回此线程的名称setPriority()/getPriority():设置和返回此线程的优先级isAlive():检测此线程是否处于活动状态,活动状态指的是程序处于正在运行或准备运行的状态sleep():使线程休眠join():等待线程执行完成yield():让同优先级的线程有执行的机会,但不能保证自己会从正在运行的状态迅速转换到可运行的状态interrupted():是线程处于中断的状态,但不能真正中断线程4.wait()和sleep()有什么区别?答:wait()和sleep()的区别主要体现在以下三个方面。存在类的不同:sleep()来自Thread,wait()来自Object。释放锁:sleep()不释放锁;wait()释放锁。用法不同:sleep()时间到会自动恢复;wait()可以使用notify()/notifyAll()直接唤醒。5.守护线程是什么?答:守护线程是一种比较低级别的线程,一般用于为其他类别线程提供服务,因此当其他线程都退出时,它也就没有存在的必要了。例如,JVM(Java虚拟机)中的垃圾回收线程。6.线程有哪些状态?答:在JDK8中,线程的状态有以下六种。NEW:尚未启动RUNNABLE:正在执行中BLOCKED:阻塞(被同步锁或者IO锁阻塞)WAITING:永久等待状态TIMED_WAITING:等待指定的时间重新被唤醒的状态TERMINATED:执行完成题目分析:JDK8线程状态的源码如下图所示:
7.线程中的start()和run()有那些区别?答:start()方法用于启动线程,run()方法用于执行线程的运行时代码。run()可以重复调用,而start()只能调用一次。8.产生死锁需要具备哪些条件?答:产生死锁的四个必要条件:互斥条件:一个资源每次只能被一个线程使用;请求与保持条件:一个线程因请求资源而阻塞时,对已获得的资源保持不放;不剥夺条件:线程已获得的资源,在末使用完之前,不能强行剥夺;循环等待条件:若干线程之间形成一种头尾相接的循环等待资源关系;这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。9.如何预防死锁?答:预防死锁的方法如下:尽量使用tryLock(longtimeout,TimeUnitunit)的方法(ReentrantLock、ReentrantReadWriteLock),设置超时时间,超时可以退出防止死锁;尽量使用Java.util.concurrent并发类代替自己手写锁;尽量降低锁的使用粒度,尽量不要几个功能用同一把锁;尽量减少同步的代码块。10.thread.wait()和thread.wait(0)有什么区别?代表什么含义?答:thread.wait()和thread.wait(0)是相同的,使用thread.wait()内部其实是调用的thread.wait(0),源码如下:publicfinalvoidwait()throwsInterruptedException{
wait(0);
}wait()表示进入等待状态,释放当前的锁让出CPU资源,并且只能等程序执行notify()/notifyAll()方法才会被重写唤醒。11.如何让两个程序依次输出11/22/33等数字,请写出实现代码?答:使用思路是在每个线程输出信息之后,让当前线程等待一会再执行下一次操作,具体实现代码如下:newThread(()->{
for(inti=1;i<4;i++){
System.out.println("线程一:"+i);
try{
Thread.sleep(100);
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}).start();
newThread(()->{
for(inti=1;i<4;i++){
System.out.println("线程二:"+i);
try{
Thread.sleep(100);
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}).start();程序执行结果如下:线程一:1线程二:1线程二:2线程一:2线程二:3线程一:312.说一下线程的调度策略?答:线程调度器选择优先级最高的线程运行,但是如果发生以下情况,就会终止线程的运行:线程体中调用了yield()方法,让出了对CPU的占用权;线程体中调用了sleep()方法,使线程进入睡眠状态;线程由于I/O操作而受阻塞;另一个更高优先级的线程出现;在支持时间片的系统中,该线程的时间片用完。总结程序的运行依靠的是进程,而进程的执行依靠的是多个线程,多线程之间可以共享一块内存和一组系统资源,而多进程间通常是相互独立的。线程的创建有三种方式:继承Thread重写run方法,实现Runnable或Callable接口,其中Callable可以允许线程的执行有返回值,JDK8中也可以使用Lambda来更加方便的使用线程,线程是有优先级的,优先级从1-10,数字越大优先级越高,也越早被执行。如果两个线程各自拥有一把锁的同时,又同时等待获取对方的锁,就会造成死锁。可以降低锁的粒度或减少同步代码块的范围或使用Java提供的安全类,来防止死锁的产生。 如何轻松获得Offer你好,我是王磊,某上市公司技术研发经理,前奇虎360员工,有着10余年的编程工作经验,目前主要负责新员工技术面试和构建企业技术架构的相关事宜。随着面试过的人数增加,我发现面试者们暴露出了技术方面的很多问题,为了让更多面试者少走一些弯路,也为了让企业能招到合适的技术人才,于是就诞生了这个专栏。为了写好这个专栏内容,我先后拜访了一二十家互联网公司,与不同的面试官和面试者进行面对面探讨,深入了解了企业对于面试者的要求和常见的Java面试题型。之后我花了大半年的时间,结合自己4年多作为面试官的经历,把这些内容整理成文,用大约10万字的内容对Java的核心知识点和常见的500多道面试题,做了详细的介绍,也就是本专栏中你所看到的全部内容,希望对你能有所帮助。为什么要学这个专栏内容?「因为它能为你赢得面试的主动权,让你获得更多的Offer。」从业十多年,我从面试者变成面试官,在Java面试上积累了比较丰富的经验。其实,很多面试者在搜集面试资料的时候都踩过一些“坑”,你是不是也遇到过:免费搜索的面试题,内容不全面,这就算了,有时候答案都不准确;很多培训机构提供的面试宝典内容虽然不少,但深度不够,且面试题过于老旧脱离了企业实际需要;还有很多付费的面试题存在滥竽充数,提供了很多没有价值的面试题,钱花了,干货没学到;市面上大部分面试题只讲了基础概念,没有提供题目解析和示例代码,不利于读者真正的掌握背后的原理,只能死记硬背,且容易忘记。为了规避这些“坑”,我跑了很多家互联网公司,来确认Java面试中实际考察的高频知识点和常见题型。可是有了第一手素材后,我要如何让大家真正从我的讲解中学到干货、用到实处呢?经过反复验证,我才设计了如下的内容讲述模式。第一,500+面试题详解。如果你是还没走入职场的新人,我会为你提供完整的Java技术栈讲解,以及最新、最全、最实用的500多道Java面试题详解。第二,10万字Java核心知识点梳理。本专栏的每一篇内容,都采用的是「核心知识点+N道相关面试题」的模式,让你不单能应付面试,还能学到更多的Java核心知识。第三,技术、面试搭配平衡,不但让你学到心里,还助你展示出来。面对目前技术市场的相对冷淡和一个职位多个应聘者竞争的现状,面试者们只有掌握更多Java核心技能和面试理论知识,才能在众多面试者中脱颖而出。本专栏每篇文章大致分为两个部分:Java核心点介绍+相关面试题详解,这两部分内容相辅相成,前面的核心知识点介绍让后面的面试题更容易理解,后面的面试题加深了读者对于Java核心点的掌握。如此一来,让你所学及所用,不仅能够应付面试,更能学习到更多有价值的Java技术点,让你在面试中和工作中都能展示的更加出色。专栏大纲本专栏分为七大部分,共计37讲,约10万字。第一部分:Java基础强化这部分包含7篇文章,我会从Java最基础的内容讲起。有最常见的String面试题从表象到原理的深入讲解;还有Java8中新特性的介绍,比如时间和日期模块,让你使用更简洁和优化的方式写出更完美的代码;还有我们日常用的很多包装类不为人知的有趣现象和知识盲点介绍;还有数组以及算法的介绍,虽然基础但容易被面试者忽略和容易出错的问题……第二部分:各种类和克隆这部分包含4篇文章,除了会深入讲解Java中的各种类和接口的相关内容,还会深入讲解浅克隆和深克隆的各种实现方式,以及配合各
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 会计专业实习日记集合7篇
- 书本《背影》读后感
- DB12T 444.1-2011 公共场所集中空调通风系统清洗消毒操作规程 第1部分:清洗
- 人生大事观后感范文
- 个人打印收入证明(6篇)
- 高等数学教程 上册 第4版 测试题及答案 -测试一-答案
- 黔西南州高二下学期语文期末考试试卷
- 九年级上学期语文期中测试模拟试卷(三)(1-4单元)
- 二年级数学计算题专项练习集锦
- 继承工龄用工协议书(2篇)
- 一年级数学老师家长会发言稿
- Linux操作系统应用(麒麟系统)PPT完整全套教学课件
- 湖北省旅游PPT简介湖北省幻灯片模板
- 大学生创新创业PPT完整全套教学课件
- 报关单位备案信息表
- 宁夏医学会超声医学分会委员候选人推荐表
- 消费者咨询业务试题及答案(4月4更新)
- 晕厥的诊断与治疗晕厥专家讲座
- 海尔bcd系列冰箱说明书
- 弘扬民族精神奔流不息民族魂
- 《观察洋葱表皮细胞》实验记录单
评论
0/150
提交评论