常见的Java线程八股

线程

1. 线程和进程的区别?

进程是当一个程序运行时候,从磁盘加载这个程序的代码到内存,这时就开启了一个进程,进程分为单实例进程和多实例进程,单实例进程就是打开的程序只能打开一份,多实例进程就是打开的程序可以打开多份。线程就是将一条一条的命令以一定顺序交给CPU执行,一个进程内包含一到多个线程。一个进程下的所有线程可以共享内存空间,线程是更轻量的,一个线程切换到另一个线程的成本更低。

2. 并行和并发有什么区别?

现在计算机都是多核CPU,并发是同一时间应对多件事情的能力,多个线程轮流使用一个或多个CPU。并行是同一时间动手做多件事情的能力,比如4核CPU同时执行4个线程。

3. 创建线程的方式有哪些?

创建线程一共有四种方式,第一种是当前类去继承Thread类 ,重写run()方法,通过new来创建当前类对象,调用start()方法来启动线程。第二种是当前类去实现Runnable接口 ,重写run()方法,通过new创建当前类对象,然后通过new创建Thread对象,将当前类对象传进去,最后调用start()方法启动线程。第三种是当前类去实现Callable<>接口 它是有返回值适合用于要拿到当前线程结果,重写call()方法,通过new创建当前类对象,再new创建FutureTask<>对象,将当前类对象传进去,然后再通过new创建Thread对象,将FutureTask<>对象传进去,调用start()方法启动线程,最后再调用FutureTask<>对象的get()方法获取结果。第四种(项目中常用)是使用线程池创建线程,首先当前类要实现Runnable接口,重写run()方法,然后创建线程池对象,使用线程池的submit()方法提交当前线程任务,线程会自动执行,最后使用线程池的shutdown()方法关闭线程池。

4. 使用 Runnable Callable 都可以创建线程,它们有什么区别呢?

Runnable是没有结果返回值的,并且它不能抛异常,而Callable有返回值的是个泛型并且可以抛异常。

5. 在启动线程的时候,可以使用 run() 方法吗? run() start() 有什么区别?

run()方法就相当于普通的方法调用,可以执行多次,而start()方法是通过线程来run()方法,只能调用一次。

6. 线程包括哪些状态?状态之间是如何变化的?

有6种状态,new、runnable、blocked、waiting、timed_waiting、terminated。首先通过new创建线程对象,执行start()方法进入runnable运行状态,如果拿到CPU执行权,正常执行后进入terminated终结状态。如果进入runnable运行状态这时候给它加了个锁,那就会进入blocked阻塞状态,释放了锁拿到执行权后才会切换回运行状态。然后如果在runnable状态调用了wait()方法就会进入waiting等待的状态,只有当调用了notify()方法后才会让它继续变成可执行状态。最后如果是调用了sleep()方法,就会进入timed_waiting时间等待状态,等到达时间就变成可运行状态。

7. 新建 T1 T2 T3 三个线程,如何保证它们按顺序执行?

可以使用线程中的join()方法解决,它就是等待线程运行结束嘛,调用了此方法的线程进入timed_waiting直到执行完此线程再继续执行,比如T2线程中的T1线程调用了join(),T3线程中的T2线程调用了join(),那就是T2要等T1执行完再执行,然后T3等T2执行完再执行。

8. notify() notifyAll() 有什么区别?

notify()是随机唤醒一个wait()的线程,而notifyAll()是唤醒所有wait()的线程。

9. Java 中的 wait() sleep() 方法有什么不同?

共同点:wait()、wait(long)、sleep(long)都能让当前线程暂时放弃CPU的使用权,进入阻塞状态。不同点:首先是方法的归属不同,sleep()是Thread的静态方法,而wait()是Object的成员方法,每个对象都有。其次是醒来的时机不同,wait(long)和sleep(long)都会等待相应毫秒后醒来,wait()、wait(long)还可以被notify唤醒,wait()如果不唤醒就一直等待下去,最后是它们都可以被打断唤醒。最后(重点)是锁特性不同,必须要加锁才能调用wait()方法,而sleep则不用加锁也能调用,wait()执行后会释放锁并进入空闲等待,允许其他线程获得该对象锁(就是我放弃CPU,但你们可以用),而sleep()如果在synchronized代码块中执行,并不会释放对象锁(我放弃CPU,你们也用不了)。

10. 如何停止一个正在运行的线程?

有3种方式可以停止线程,第一种是加上退出标记,达到退出标记时间使线程正常退出,也就是当run()方法完成后线程终止。第二种是使用stop()方法强行终止(已作废,不推荐)。第三种是使用interrupt()方法中断线程,它分为2种情况,首先是打断阻塞的线程(wait、sleep、join)的线程,线程会抛出InterrupteException异常,然后就是打断正常的线程,根据打断状态来标记是否退出线程。

相关推荐
全栈老石13 分钟前
Python 异步生存手册:给被 JS async/await 宠坏的全栈工程师
后端·python
大模型玩家七七15 分钟前
梯度累积真的省显存吗?它换走的是什么成本
java·javascript·数据库·人工智能·深度学习
space621232721 分钟前
在SpringBoot项目中集成MongoDB
spring boot·后端·mongodb
CodeToGym1 小时前
【Java 办公自动化】Apache POI 入门:手把手教你实现 Excel 导入与导出
java·apache·excel
凡人叶枫1 小时前
C++中智能指针详解(Linux实战版)| 彻底解决内存泄漏,新手也能吃透
java·linux·c语言·开发语言·c++·嵌入式开发
Tony Bai1 小时前
再见,丑陋的 container/heap!Go 泛型堆 heap/v2 提案解析
开发语言·后端·golang
JMchen1231 小时前
Android后台服务与网络保活:WorkManager的实战应用
android·java·网络·kotlin·php·android-studio
阔皮大师1 小时前
INote轻量文本编辑器
java·javascript·python·c#
寻找奶酪的mouse1 小时前
30岁技术人对职业和生活的思考
前端·后端·年终总结
小法师爱分享2 小时前
StickyNotes,简单便签超实用
java·python