面试必备——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 ...
随机推荐
- Sqoop import export参数
通用参数 import export 通用通用参数选项 含义说明–connect 指定JDBC连接字符串–connection-manager 指定要使用的连接管理器类–dri ...
- 2019牛客暑期多校训练营(第五场)G-subsequence 1
>传送门< 题意:给你两个数字字符串s,t,求字符串s的子序列比字符串t大的个数 思路:他的题解上写的就是dp的基础练习题,好像的确是这么回事,既然是dp,那么对于定义的状态不同得到的转移 ...
- 【hdu 3579】Hello Kiki(数论--拓展欧几里德 求解同余方程组)
题意:Kiki 有 X 个硬币,已知 N 组这样的信息:X%x=Ai , X/x=Mi (x未知).问满足这些条件的最小的硬币数,也就是最小的正整数 X. 解法:转化一下题意就是 拓展欧几里德求解同余 ...
- 【noi 2.6_6046】数据包的调度机制(区间DP)
题意:给定一个队列延迟值为Di的任务,以任意顺序入栈和出栈,第K个出栈的延迟值为(K-1)*Di.问最小的延迟值. 解法:f[i][l]表示完成以第i个任务开始,长度为l,到第i+l-1个任务的最小延 ...
- nuoyanli 520 Let‘s play computer game
H题 描述 xxxxxxxxx在疫情期间迷上了一款游戏,这个游戏一共有nnn个地点(编号为1--n1--n1--n),他每次从一个地点移动到另外一个地点需要消耗 一定的能量,每一个地点都有一些珠宝,输 ...
- Nginx location相关配置说明
Nginx location相关配置说明 基于不同的IP.不同的端口以及不用得域名实现不同的虚拟主机,依赖于核心模块ngx_http_core_module实现. 新建PC web站点 [ ...
- CS144学习(1)Lab 0: networking warmup
CS144的实验就是要实现一个用户态TCP协议,对于提升C++的水平以及更加深入学习计算机网络还是有很大帮助的. 第一个Lab是环境配置和热身,环境按照文档里的配置就行了,前面两个小实验就是按照步骤来 ...
- 【非原创】codeforces 1060E Sergey and Subway 【树上任意两点距离和】
学习博客:戳这里 本人代码: 1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 con ...
- 017.NET5_内置容器基本使用
IOC容器IServiceCollection .net 5已经内置了IOC容器. 什么是IOC? 把对象的创建交给第三方容器去创建 如何使用内置的 IOC IServiceCollection ? ...
- asp.net 从Excel表导入数据到数据库中
http://www.cnblogs.com/hfzsjz/archive/2010/12/31/1922901.html http://hi.baidu.com/ctguyg/item/ebc857 ...