Java面试总结(六)
进程和线程的区别
根本区别: 进程时操作系统资源分配的基本单位,而线程是处理器任务调度和执行的基本单位。
资源开销: 每个进程都有自己独立的代码和数据空间(程序上下文),进程之间的切换开销比较大;线程可以看作轻量级进程,同类的线程共享进程的堆和方法区(JDK1.7及之前实现为永久代,JDK1.8及之后实现为元空间)资源,但是每个线程都有自己的程序计数器、Java虚拟机栈和本地方法栈,线程之间的切换开销比较小。
包含关系: 如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。
内存分配: 同一进程的线程共享本进程的地址空间和资源,而进程之间的地址空间和资源是相互独立的。
影响关系: 一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉,所以多进程要比多线程健壮。
执行过程: 每个独立的进程有程序运行的入口、顺序执行序列和程序出口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制,两者均可并发执行。
总结: 线程是进程划分成的更小的运行单位。线程和进程最大的不同在于基本上各进程是独立的,而各线程则不一定,因为同一进程中的线程极有可能会相互影响。线程执行开销小,但不利于资源的管理和保护;而进程正相反。
创建线程的三种方式
使用继承Thread类的方式创建多线程
Thread类是Java提供的线程顶级类,继承Thread类可快速定义线程。
- 使用多线程实现龟兔赛跑
public class TortoiseThread extends Thread{@Overridepublic void run() {while (true) {System.out.println("乌龟领先了,加油.....," +"当前线程的名称:" + this.getName() +",当前线程的优先级别:" + this.getPriority());}}public static void main(String[] args) {TortoiseThread tortoiseThread = new TortoiseThread();tortoiseThread.setName("乌龟线程");tortoiseThread.start();Thread.currentThread().setName("兔子线程");while(true){System.out.println("兔子领先了,add oil....,当前线程名称:"+Thread.currentThread().getName()+",当前线程的优先级别:"+Thread.currentThread().getPriority());}}
}
- 运行结果截取(这里只截取了部分结果,应该是无限循环的)
乌龟领先了,加油.....,当前线程的名称:乌龟线程,当前线程的优先级别:5
乌龟领先了,加油.....,当前线程的名称:乌龟线程,当前线程的优先级别:5
兔子领先了,add oil....,当前线程名称:兔子线程,当前线程的优先级别:5
兔子领先了,add oil....,当前线程名称:兔子线程,当前线程的优先级别:5
使用实现Runnable接口的方式创建多线程
- 使用多线程实现龟兔赛跑
public class TortoiseRunnable implements Runnable{@Overridepublic void run() {while (true) {System.out.println("乌龟领先了,加油.....," +"当前线程的名称:" + Thread.currentThread().getName() +",当前线程的优先级别:" + Thread.currentThread().getPriority());}}public static void main(String[] args) {Thread thread = new Thread(new TortoiseRunnable());thread.setName("乌龟线程");thread.start();Thread.currentThread().setName("兔子线程");while(true){System.out.println("兔子领先了,add oil....,当前线程名称:"+Thread.currentThread().getName()+",当前线程的优先级别:"+Thread.currentThread().getPriority());}}
}
- 运行结果截取(这里只截取了部分结果,应该是无限循环的)
乌龟领先了,加油.....,当前线程的名称:乌龟线程,当前线程的优先级别:5
乌龟领先了,加油.....,当前线程的名称:乌龟线程,当前线程的优先级别:5
兔子领先了,add oil....,当前线程名称:兔子线程,当前线程的优先级别:5
兔子领先了,add oil....,当前线程名称:兔子线程,当前线程的优先级别:5
使用实现Callable接口的方式创建多线程
- 使用多线程实现龟兔赛跑
public class TortoiseCallable implements Callable {@Overridepublic Object call() throws Exception {while (true) {System.out.println("乌龟领先了,加油.....," +"当前线程的名称:" + Thread.currentThread().getName() +",当前线程的优先级别:" + Thread.currentThread().getPriority());}}public static void main(String[] args) {TortoiseCallable tortoiseCallable = new TortoiseCallable();FutureTask futureTask = new FutureTask(tortoiseCallable);Thread thread = new Thread(futureTask);thread.setName("乌龟线程");thread.start();Thread.currentThread().setName("兔子线程");while(true){System.out.println("兔子领先了,add oil....,当前线程名称:"+Thread.currentThread().getName()+",当前线程的优先级别:"+Thread.currentThread().getPriority());}}
}
- 运行结果截取(这里只截取了部分结果,应该是无限循环的)
乌龟领先了,加油.....,当前线程的名称:乌龟线程,当前线程的优先级别:5
乌龟领先了,加油.....,当前线程的名称:乌龟线程,当前线程的优先级别:5
兔子领先了,add oil....,当前线程名称:兔子线程,当前线程的优先级别:5
兔子领先了,add oil....,当前线程名称:兔子线程,当前线程的优先级别:5
创建三种线程的方式对比
使用实现Runnable、Callable接口的方式创建多线程。
-
优势:
Java的设计是单继承的设计,如果使用继承Thread的方式实现多线程,则不能继承其他的类,而如果使用实现Runnable接口或Callable接口的方式实现多线程,还可以继承其他类。
采用接口能够更好的实现数据共享。线程的启动需要Thread类的start方法,如果采用继承的方式每次新建一个线程时,每个新建线程的数据都会单独的存在线程内存中,这样每个线程会单独的操作自己线程的数据,不能更好的实现线程之间的数据共享。 -
劣势:
编程稍微复杂,如果要访问当前线程,则必须使用Thread.currentThread()方法。
使用继承Thread类的方式创建多线程
-
优势:
编写简单,如果需要访问当前线程,则无需使用Thread.currentThread()方法,直接使用this即可获得当前线程。 -
劣势:
线程类已经继承了Thread类,所以不能再继承其他的类。
Runnable和Callable的区别
与Runnable相比,Callable功能更强大些
- Callable规定(重写)的方法是call(),Runnable规定(重写)的方法是run()。
- Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。
- call方法可以抛出异常,run方法不可以。
- Callable是支持泛型的
- 运行Callable任务可以拿到一个Future对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。
Runnable接口源码
@FunctionalInterface
public interface Runnable {public abstract void run();
}
Callable接口源码
@FunctionalInterface
public interface Callable<V> {/*** Computes a result, or throws an exception if unable to do so.** @return computed result //可以有返回值* @throws Exception if unable to compute a result //可以抛出异常*/V call() throws Exception;
}
Callable接口使用案例
/*
创建线程的方式三:实现Callable接口。-----JDK1.5新增*/
//1.创建一个实现Callable的实现类
class NumThread implements Callable{//2.实现call方法,将此线程需要执行的操作声明在call()中@Overridepublic Object call() throws Exception{int sum=0;for (int i=1;i<=100;i++){sum+=i;}return sum;}
}
public class ThreadNew {public static void main(String[] args) throws ExecutionException, InterruptedException {//3.创建Callable接口实现类的对象NumThread numThread=new NumThread();//4.将此Callable接口实现类的对象作为传递到FutureTask构造中,创建FutureTask的对象FutureTask futureTask=new FutureTask(numThread);//5.将FutureTask的对象组排位哦参数传递到thread类的构造器中,创建Thread对象,并调用start()new Thread(futureTask).start();//6.获取Callable中call方法的返回值//get()返回值即为FutureTask构造器参数Callable实现类重写的call()的返回值Object sum = futureTask.get();System.out.println("总和为:"+sum);}
}
线程的状态
- NEW:初始状态,线程刚刚被创建出来,还没有调用 start() 方法;
- RUNABLE:运行中状态,调用了 start() 方法,Java 线程将操作系统中的 就绪/可运行(READY)状态和 运行(RUNNING)状态统称为 RUNABLE 状态;
- BLOCK:阻塞状态,线程阻塞于锁,需要等待锁的释放;
- WAITING:等待状态,进入等待状态表示需要等待其他线程做出一些特定的状态(通知或中断);
- TIMED_WAITING:超时等待状态,可以在指定时间后自行返回,而不是像WAITING状态一样一直等待;
- TEMENATED:终止状态,表示当前线程已经执行完毕。
-
由上图可以看出:线程创建之后它将处于 NEW(初始) 状态,调用 start() 方法后开始运行,线程这时候处于 READY(就绪/可运行) 状态。可运行状态的线程获得了 CPU 时间片(timeslice)后就处于 RUNNING(运行) 状态。
-
在操作系统层面,线程有 READY 和 RUNNING 状态;而在 JVM 层面,只能看到 RUNNABLE 状态,所以 Java 系统一般将这两个状态统称为 RUNNABLE(运行中) 状态 。
-
为什么 JVM 没有区分这两种状态呢?
java 现在的时分(time-sharing)多任务(multi-task)操作系统架构通常都是用所谓的“时间分片(time quantum or time slice)”方式进行抢占式(preemptive)轮转调度(round-robin 式)。这个时间分片通常是很小的,一个线程一次最多只能在 CPU 上运行比如 10-20ms 的时间(此时处于 running 状态),也即大概只有 0.01 秒这一量级,时间片用后就要被切换下来放入调度队列的末尾等待再次调度。(也即回到 ready 状态)。线程切换的如此之快,区分这两种状态就没什么意义了。
-
当线程执行 wait()方法之后,线程进入 WAITING(等待) 状态。进入等待状态的线程需要依靠其他线程的通知才能够返回到运行状态。
-
TIMED_WAITING(超时等待) 状态相当于在等待状态的基础上增加了超时限制,比如通过 sleep(long millis)方法或 wait(long millis)方法可以将线程置于 TIMED_WAITING 状态。当超时时间结束后,线程将会返回到 RUNNABLE 状态。
-
当线程进入 synchronized 方法/块或者调用 wait 后,(被 notify)想要重新进入 synchronized 方法/块时,但是锁被其它线程占有,这个时候线程就会进入 BLOCKED(阻塞) 状态。
-
线程在执行完了 run()方法之后将会进入到 TERMINATED(终止) 状态。
相关文章:

Java面试总结(六)
进程和线程的区别 根本区别: 进程时操作系统资源分配的基本单位,而线程是处理器任务调度和执行的基本单位。 资源开销: 每个进程都有自己独立的代码和数据空间(程序上下文),进程之间的切换开销比较大&…...

Windows逆向安全(一)C与汇编的关系
前言 逆向是一种新型的思维模式也是软件开发领域中极为重要的技术,涵盖各种维度去深挖软件架构的本质和操作系统原理,学习逆向后可以在各领域中发挥至关重要的作用,其中包括黑灰色,安全开发,客户端安全,物…...

Lazada、Allegro、速卖通测评自养号技术(方法解析)
无论是亚马逊、拼多多Temu、shopee、Lazada、wish、速卖通、煤炉、敦煌、雅虎、eBay、TikTok、Newegg、乐天、美客多、阿里国际、沃尔玛、OZON、Joom、Facebook、Coupang、独立站、Cdiscount、Kaufland、DARTY、Allegro、MANO等平台测评自养号对于卖家来说算是一种低成本、高回…...

Vue3的composition API—setup函数, ref函数,reactive函数
1、Setup 函数 1.setup 是vue3中的一个配置项 2、setup是所有组件所需要的数据和方法都需要配置到setup中的 3、setup两种返回值: 若返回一个对象 若返回一个渲染函数 mian.js文件 注意:尽量不与Vue2混用 setup中无法访问vue2中的配置 不能是async函数…...

国外seo比较好的优化方法有哪些?
随着互联网的不断发展,SEO(搜索引擎优化)变得越来越重要。 对于国外市场,Google搜索引擎是最为重要的搜索引擎之一, 因此在优化国外网站时,需要将Google SEO优化作为首要任务。 关键词研究和优化 在进行…...

【JavaEE进阶】——第一节.Maven国内源配置
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 操作步骤 1.打开项目配置界面(当前项目配置) 2.检查并配置国内源 3.再次打开项目配置界面(新项目配置) 4…...
dockerFile编写
dockerFile编写 语法参数 # DockerFile常用指令 USER # 指定运行的用户,一般不用配置 FROM # 拉取基础镜像,一切从这里开始构建 ARG # 构建参数,只能在dockerFile中使用, # eg: JAR_FILEtarget/springboot-mongo-0.0.1-SNAPSHOT.jar MAI…...

jenkins扩展你的流水线
文章目录一、概述二、可信库和不可信库可信库不可信库三、内部库与外部库内部库SSH访问HTTP 访问外部库配置一个外部库四、在流水线脚本中使用库从源码版本控制中自动下载库加载库到脚本中Library 注解库步骤库指令五、Jenkins 项目中的库范围六、共享库代码的结构src示例一&am…...
Golang模糊测试入门
本教程介绍了 Go 中模糊测试的基础知识。通过模糊测试,随机数据会针对您的测试运行,以试图找到漏洞或导致崩溃的输入。可以通过模糊测试发现的一些漏洞示例包括 SQL 注入、缓冲区溢出、拒绝服务和跨站点脚本攻击。 在本教程中,您将为一个简单的函数编写模糊测试,运行 go 命…...

ARM uboot 的移植4 -从 uboot 官方标准uboot开始移植
一、添加DDR初始化1 1、分析下一步的移植路线 (1) cpu_init_crit 函数成功初始化串口、时钟后,转入 _main 函数,函数在 arch/arm/lib/crt0.S 文件中。 (2) 在 crt0.S 中首先设置栈,将 sp 指向 DDR 中的栈地址; #if defined(CONF…...

不用索引怎么优化百亿数据? | MySQL性能优化篇
文章目录数据库调优一、数据库调优原理1.1 为什么要进行MySQL数据库调优?1.2 什么影响数据库性能?1.3 数据库调优到底调什么?二、数据库压力测试2.1 什么是压测?2.2 JMeter简介2.3 驱动下载2.4 测试过程三、连接池3.1 压力测试连接…...

JavaScript(WebAPI)
目录 1.什么是Web API? 2.DOM和DOM树 3.获取元素 4.事件 5.操作元素 获取/修改元素内容 1.innerText 2. innerHTML 获取/修改元素属性 获取/修改表单元素属性 获取/修改样式属性 1.修改内联样式 2.修改元素应用的CSS类名 6.操作节点 新增节点 删除节点 7.案例…...

idea集成GitHub
设置 GitHub 账号绑定账号有两种方式:1. 通过授权登录2.如果上述登录不成功,用Token口令的方式登录,口令在github账号哪里生成,点击settings --->Developer settings --->pwrsonal access tokens ----> 复制口令到idea 口…...
软考高级信息系统项目管理师系列之四十一:项目组合管理
软考高级信息系统项目管理师系列之四十一:项目组合管理 一、项目组合管理内容二、项目组合管理基础概述1.项目组合定义及相关知识图2.项目组合、项目集和项目之间的关系3.项目组合模块具备的特征三、项目组合管理1.项目组合管理定义及要求2.不同级别管理之间的特性及关联3.项目…...

Spring——Spring整合Mybatis(XML和注解两种方式)
框架整合spring的目的:把该框架常用的工具对象交给spring管理,要用时从IOC容器中取mybatis对象。 在spring中应该管理的对象是sqlsessionfactory对象,工厂只允许被创建一次,所以需要创建一个工具类,把创建工厂的代码放在里面&…...

【专项训练】布隆过滤器和LRU缓存
布隆过滤器:与哈希表类似 哈希表是一个没有误差的数据结构! 有哈希函数得到index,会把要存的整个元素放在哈希表里面 有多少元素,每个元素有多大,所有的这些元素需要占的内存空间,在哈希表中都要找相应的内存大小给存起来 事实上,我们并不需要存所有的元素本身,而是只…...

从一道面试题看 TCP 的吞吐极限
分享一个 TCP 面试题:单条 TCP 流如何打满香港到旧金山的 320Gbps 专线?(补充,写成 400Gbps 更具迷惑性,但预测大多数人都会跑偏,320Gbps 也就白给了) 这个题目是上周帮一个朋友想的,建议他别问三次握手&a…...
rsync 的用法
rsync 介绍下 用法 rsync是一个常用的数据同步工具,它能够在本地和远程系统之间同步文件和目录。以下是rsync的基本用法: 同步本地文件夹: bash Copy code rsync -av /path/to/source /path/to/destination其中,-a表示归档模式&…...

【LeetCode每日一题:[面试题 17.05] 字母与数字-前缀和+Hash表】
题目描述 给定一个放有字母和数字的数组,找到最长的子数组,且包含的字母和数字的个数相同。 返回该子数组,若存在多个最长子数组,返回左端点下标值最小的子数组。若不存在这样的数组,返回一个空数组。 示例 1: 输入…...
华为OD机试题 - 简易压缩算法(JavaScript)| 机考必刷
更多题库,搜索引擎搜 梦想橡皮擦华为OD 👑👑👑 更多华为OD题库,搜 梦想橡皮擦 华为OD 👑👑👑 更多华为机考题库,搜 梦想橡皮擦华为OD 👑👑👑 华为OD机试题 最近更新的博客使用说明本篇题解:简易压缩算法题目输入输出示例一输入输出说明示例二输入输出说明…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...

C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
安卓基础(Java 和 Gradle 版本)
1. 设置项目的 JDK 版本 方法1:通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分,设置 Gradle JDK 方法2:通过 Settings File → Settings... (或 CtrlAltS)…...
libfmt: 现代C++的格式化工具库介绍与酷炫功能
libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库,提供了高效、安全的文本格式化功能,是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全:…...
提升移动端网页调试效率:WebDebugX 与常见工具组合实践
在日常移动端开发中,网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时,开发者迫切需要一套高效、可靠且跨平台的调试方案。过去,我们或多或少使用过 Chrome DevTools、Remote Debug…...

ubuntu22.04有线网络无法连接,图标也没了
今天突然无法有线网络无法连接任何设备,并且图标都没了 错误案例 往上一顿搜索,试了很多博客都不行,比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动,重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...