面试必备——Java多线程与并发(一)
1.进程和线程的
(1)由来
1)串行
2)批处理
存在问题:
3)进程
4)线程
(2)区别
- 所有与进程相关的资源,都被记录在PCB(进程控制块)中
进程是抢占处理器的调度单位;线程属于某个进程,共享其资源
线程只由堆栈寄存器、程序计数器和TCB组成
总结
- 线程不能看做独立应用,而进程可看做独立应用
- 进程有独立的地址空间,相互不影响,线程只是进程的不同执行路径
- 进程数据分开,共享复杂,同步简单;线程共享简单,同步复杂
- 线程没有独立的地址空间,多进程的程序比多线程程序健壮(进程出现问题不会影响其他进程,可靠高;一个线程挂掉,整个进程也会挂掉,可靠低)
- 进程的切换比线程的切换开销大(进程单独占有一定的内存地址空间,进程的创建和销毁不仅需要保存寄存器和栈信息,还需要资源的分配回收以及页调度,开销较大;线程只需要保存寄存器和栈信息,开销较小)
(3)JAVA进程和线程的关系
- Java对操作系统提供的功能进行封装,包括进程和线程
- 运行一个程序会产生一个进程,进程包含至少一个线程
- 每个进程对应一个JVM实例,多个线程共享JVM里的堆,JVM是多线程的
- Java采用单线程编程模型,程序会自动创建主线程
- 主线程可以创建子线程,原则上要后于子线程完成执行,因为要执行各种关闭动作
2.线程的start和run的区别
- 调用start()方法会创建一个新的子线程并启动
- run()方法只是Thread的一个普通方法的调用
3.Thread和Runnable是什么关系
- Thread是实现了Runnable接口的类,通过Thread的start()方法可以给Runnable的run()方法附上多线程的特性
- 因Java类的单一继承原则,推荐多使用Runnable接口(为了提升系统的可拓展性,通过使业务类实现Runnable接口,将业务逻辑封装在run方法里,后续可以给普通类附上多线程的特性)
4.如何实现处理线程的返回值
(1)主线程等待法:实现简单,我们可以通过实现循环等待的逻辑;缺点是变量多的时候会显得臃肿,无法精准控制

1 public class CycleWait implements Runnable {
2
3 private String value;
4
5 @Override
6 public void run() {
7 try {
8 Thread.currentThread().sleep(5000);
9 } catch (InterruptedException e) {
10 e.printStackTrace();
11 }
12 value = "we have date now";
13 }
14
15 public static void main(String[] args) throws InterruptedException {
16 CycleWait cw = new CycleWait();
17 Thread t = new Thread(cw);
18 t.start();
19 //当值为null的时候一直循环,直到有值时才退出循环
20
21 while (cw.value == null) {
22
23 Thread.currentThread().sleep(100);
24
25 }
26 System.out.println("value:" + cw.value); // 没有前面的循环,可能取出的值为null
27 }
28 }
(2)使用Thread类的join()阻塞当前线程以等待子线程处理完毕:实现更简单,缺点是力度不够细,无法精确控制

1 public static void main(String[] args) throws InterruptedException {
2 CycleWait cw = new CycleWait();
3 Thread t = new Thread(cw);
4 t.start();
5 t.join();
6 System.out.println("value:" + cw.value);
7 }
(3)通过Callable接口实现:JDK5.0新增的,具体可以通过FutureTask或线程池获取

1 public class myCallable implements Callable {
2 @Override
3 public String call() throws Exception {
4 String value = "test";
5 System.out.println("Ready to work");
6 Thread.currentThread().sleep(3000);
7 System.out.println("task done");
8 return value;
9 }
10 }
- FutureTask

1 public static void main(String[] args) throws ExecutionException, InterruptedException {
2 FutureTask<String> ft = new FutureTask<String>(new myCallable());
3 new Thread(ft).start();
4 if (!ft.isDone()) {
5 System.out.println("task has not finished, please wait!");
6 }
7 System.out.println("task reture:" + ft.get());
8 }
- 线程池

1 public static void main(String[] args) {
2 ExecutorService executorService = Executors.newCachedThreadPool();
3 Future<String> future = executorService.submit(new myCallable());
4 if (!future.isDone()) {
5 System.out.println("task has not finished, please wait!");
6 }
7 try {
8 System.out.println("task reture:" + future.get());
9 } catch (InterruptedException e) {
10 e.printStackTrace();
11 } catch (ExecutionException e) {
12 e.printStackTrace();
13 } finally {
14 executorService.shutdown();
15 }
16 }
运行结果
1 task has not finished, please wait!
2 Ready to work
3 task done
4 task reture:test
5.线程的状态(6个)
(1)新建(New):创建后尚未启动的线程的状态
(2)运行(Runnable):包含Running和Ready(Running:正在执行;Ready:等待CPU分配执行时间)
(3)无限期等待(Waiting):不会被分配CPU执行时间,需要显示被唤醒
- 没有设置Timeout参数的Object.wait()方法
- 没有设置Timeout参数的Thread.join()方法
- LockSupport.park()方法
(4)限期等待(Timed Waiting):在一定时间后由系统自动唤醒
- Thread.sleep()方法
- 设置了Timeout参数的Object.wait()方法
- 设置了Timeout参数的Thread.join()方法
- LockSupport.parkNanos()方法
- LockSupport.parkUntil()方法
(5)阻塞(Blocked):等待获取排它锁
(6)结束(Terminated):已终止线程的状态,线程已经结束执行
6.sleep和wait的区别
(1)基本差别
- sleep是Thread类的方法,wait是Object类中定义的方法
- sleep()方法可以在任何地方使用
- wait()方法只能在synchronized方法或synchronized块中使用
(2)最主要的本质区别
- Thread.sleep只会让出CPU,不会释放锁
- Object.wait不仅会让出CPU,还会释放锁(这个方法要写在synchronized里面,因为要获得锁,才能释放锁)
7.notify和notifyall的区别
(1)需要先了解的两个概念
- 锁池EntryList
- 等待池WaitSet
(2)区别
- notifyAll会让所有处于等待池的线程全部进入锁池去竞争获取锁的机会
- notify只会随机选取一个处于等待池中的线程进入锁池去竞争获取锁的机会
8.yield相关
当调用Thread.yield()函数时,会给线程调度器一个当前线程愿意让出CPU使用的暗示,但是线程调度器可能会忽略这个暗示,该方法不释放锁。

1 public static void main(String[] args) {
2 Runnable yieldTask = () -> {
3 for (int i = 0; i <= 10; i++) {
4 System.out.println(Thread.currentThread().getName() + i);
5 if (i == 5){
6 Thread.yield(); // 暗示线程调度器愿意让出CPU使用,但最终决定权还是在线程调度器中
7 }
8 }
9 };
10 Thread thread1 = new Thread(yieldTask,"A");
11 Thread thread2 = new Thread(yieldTask,"B");
12 thread1.start();
13 thread2.start();
14 }
9.interrupt相关
(1)设计理念
(2)如何中断线程
1)已经被抛弃的方法
- 通过调用stop()方法停止线程
- 通过调用suspend()和resume()方法
2)目前使用的方法
- 如果线程处于被阻塞状态,那么线程立即退出被阻塞状态,并抛出一个InterruptedException异常
- 如果线程处于正常活动状态,那么会将该线程的中断标志设置为true。被设置中断标志的线程将继续正常运行,不受影响
- 在正常运行任务时,经常检查本线程的中断标志位,如果被设置了中断标志就自行停止线程
- 调用Thread.interrupted() 方法后线程恢复非中断状态,即Thread.currentThread().isInterrupted()是false
面试必备——Java多线程与并发(一)的更多相关文章
- 面试必备——Java多线程与并发(二)
1.synchroized相关(锁的是对象,不是代码) (1)线程安全问题的主要原因 存在共享数据(也称临界资源) 存在多线程共同操作这些共享数据 解决:同一时刻有且只有一个线程在操作共享数据,其他线 ...
- 互联网校招面试必备——Java多线程
本文首发于我的个人博客:尾尾部落 本文是我刷了几十篇一线互联网校招java后端开发岗位的面经后总结的多线程相关题目,虽然有点小长,但是面试前看一看,相信能帮你轻松啃下多线程这块大骨头. 什么是进程,什 ...
- JAVA多线程和并发基础面试问答(转载)
JAVA多线程和并发基础面试问答 原文链接:http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-ans ...
- [转] JAVA多线程和并发基础面试问答
JAVA多线程和并发基础面试问答 原文链接:http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-ans ...
- JAVA多线程和并发基础面试问答
转载: JAVA多线程和并发基础面试问答 多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一.在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握Java多线程基础知识来对 ...
- 【多线程】JAVA多线程和并发基础面试问答(转载)
JAVA多线程和并发基础面试问答 原文链接:http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-ans ...
- (转)JAVA多线程和并发基础面试问答
JAVA多线程和并发基础面试问答 原文链接:http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-ans ...
- JAVA多线程和并发基础面试问答【转】
JAVA多线程和并发基础面试问答 多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一.在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握Java多线程基础知识来对应日后碰 ...
- 17、JAVA多线程和并发基础面试问答
JAVA多线程和并发基础面试问答 原文链接:http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-ans ...
随机推荐
- django开发东京买菜,全栈项目,前端vue,带手机GPS精准定位,带发票系统,带快递系统,带微信/支付宝/花呗/银行卡支付/带手机号一键登陆,等等
因为博客园不能发视频,所以,完整的视频,开发文档,源码,请向博主索取 完整视频+开发文档+源码,duanshuiLu.com下载 vue+django手机购物商城APP,带支付,带GPS精准定位用户, ...
- hdu 6835 Divisibility 思维
题意: 给你一个10进制的b和x,对于任意的一个b进制的y.如果y每一位的和可以被x整除,且y可以被x整除:或者如果y每一位的和不可以被x整除,且y不可以被x整除.那么就输出T.否则输出F 题解: 代 ...
- Codeforces Round #594 (Div. 2) C. Ivan the Fool and the Probability Theory (思维,递推)
题意:给你一个\(n\)x\(m\)的矩阵,需要在这些矩阵中涂色,每个格子可以涂成黑色或者白色,一个格子四周最多只能有\(2\)个和它颜色相同的,问最多有多少种涂色方案. 题解:首先我们考虑一维的情况 ...
- read()、readline()、readlines() -- Python
文本文件:readfile.txt 详细描述: read() #一次性读取文本中全部的内容,以字符串的形式返回结果 readline() #只读取 ...
- pip&conda 换源
PIP 各种可用源 清华源:https://pypi.tuna.tsinghua.edu.cn/simple 临时指定源 pip install -i https://pypi.tuna.tsingh ...
- 牛年 dotnet云原生技术趋势
首先祝大家:新年快乐,牛年大吉,牛年发发发! 2020年的春节,新冠疫情使得全球业务停滞不前,那时候,没有人知道会发生什么,因此会议被取消,合同被搁置,项目被推迟,一切似乎都停止了.但是我们却见证了I ...
- 域渗透——获得域控服务器的NTDS.dit文件
0x00 前言 在之前的文章<导出当前域内所有用户hash的技术整理>曾介绍过通过Volume Shadow Copy实现对ntds.dit文件的复制, 可用来导出域内所有用户hash.本 ...
- Chrome V8 引擎源码剖析
Chrome V8 引擎源码剖析 V8 https://github.com/v8/v8 array & sort https://github.com/v8/v8/search?l=Java ...
- 同城速递 & 同城跑腿 & 竞品分析
同城速递 & 同城跑腿 & 竞品分析 toC / toB 闪送 https://www.ishansong.com/ https://www.tianyancha.com/compan ...
- Node.js & BFF & FaaS
Node.js & BFF & FaaS server https://github.com/PacktPublishing/Node.js-Web-Development-Fourt ...