多线程面试题目(1)

多线程基础

什么是多线程?多线程的优点与缺点?

多线程:多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务。

优点:可以提高 CPU 的利用率。在多线程程序中,一个线程必须等待的时候,CPU 可以运行其它的线程而不是等待,这样就大大提高了程序的效率。也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。

缺点

  • 线程也是程序,所以线程需要占用内存,线程越多占用内存也越多
  • 多线程需要协调和管理,所以需要CPU时间跟踪线程
  • 线程之间对共享资源的访问会相互影响,必须解决竞用共享资源的问题

创建线程的四种方式

继承Thread类,java是单继承
  • 定义Thread类的子类,并重写该类的run()方法,该方法的方法体就是线程需要完成的任务,run()方法也称为线程执行体;
  • 创建Thread子类的实例,也就是创建了线程对象
  • 启动线程,调用线程的start()方法
public class CreateThread extends Thread{@Overridepublic void run() {//获取线程名System.out.println(Thread.currentThread().getName());}public static void main(String[] args) {CreateThread createThread = new CreateThread();//线程启动createThread.start();}
}
实现Runnable接口
  • 定义Runnable接口的实现类,一样要重写run()方法,这个run()方法和Thread中的run()方法一样是线程的执行体。
  • 创建Runnable实现类的实例,并用这个实例作为Thread的target来创建Thread对象,这个Thread对象才是真正的线程对象。
  • 调用线程对象的start()方法来启动线程。
public class RunnableCreateThread implements Runnable{@Overridepublic void run() {System.out.println("实现Runnable接口创建线程");}public static void main(String[] args) {new Thread(new RunnableCreateThread()).start();}
}

匿名内部类:

new Thread(new Runnable() {@Overridepublic void run() {// 调用资源方法,完成业务逻辑}
}, "your thread name").start();

lambda表达式:

new Thread(() -> {}, "your thread name").start();
  • 实现Callable接口
  • 使用Executor工具类创建线程池
使用Callable和Future创建线程

与 Runnable 接口不一样,Callable 接口提供了一个 call() 方法作为线程执行体,call() 方法比 run() 方法功能要强大,比如:call() 方法可以有返回值、call() 方法可以声明抛出异常。

  • 创建实现 Callable 接口的类 CreateThread1;
  • 以 createThread1为参数创建 FutureTask 对象;
  • 将 FutureTask 作为参数创建 Thread 对象
  • 调用线程对象的 start() 方法
public class CreateThread1 implements Callable {@Overridepublic Object call() throws Exception {System.out.println(Thread.currentThread().getName());return "call() 方法可以有返回值、call() 方法可以声明抛出异常";}public static void main(String[] args) {//创建 FutureTask 对象FutureTask futureTask = new FutureTask<>(new CreateThread1());//创建线程并启动Thread thread = new Thread(futureTask);thread.start();try {Thread.sleep(1000);//获取返回值System.out.println("返回的结果是:" + futureTask.get());} catch (Exception e) {e.printStackTrace();}}
}
基于线程池创建线程

(可去查看线程池的章节)

public class CreateThreadByExecutors implements Runnable {public static void main(String[] args) {ExecutorService service = Executors.newSingleThreadExecutor();CreateThreadByExecutors thread = new CreateThreadByExecutors();for (int i = 0; i < 10; i++) {service.execute(thread);System.out.println("=======任务开始=========");service.shutdown();}}@Overridepublic void run() {System.out.println("hello Thread");}
}

Runnablecallable有什么区别

相同点:

  • 两个都是接口。
  • 都是编写多线程程序。
  • 都是采用Thread.start()启动程序。

区别:

  • Runnable的**run()方法无返回值,callable的call()**方法提供返回值用来表示任务运行的结果。
  • Runnable提供**run()方法,无法通过throws抛出异常,异常必须在run()方法内部处理。callable提供call()**方法,直接抛出异常。

线程的状态有哪些

线程5个状态:创建、就绪、运行、阻塞和死亡。

  • 新建(new):新创建了一个线程对象。
  • 就绪(runnable):线程对象创建后,当调用线程对象的start()方法,该线程可能处于运行状态,可能处于就绪状态,等待被线程调度选中,获取cpu使用权。
  • 运行(running):线程获取CPU权限执行
  • 阻塞(blocked):阻塞包含三种情况:等待阻塞,同步阻塞,其他阻塞
    • 等待阻塞:wait(),进入等待队列,需要notify唤醒(但notify唤醒的线程是随机的)
    • 同步阻塞:获取同步锁失败进入阻塞
    • 其他阻塞:sleep(),join(),发出IO请求
  • 等待(WAITING)
  • 定时等待(Timed Waiting)
  • 消亡(terminated):线程执行结束

线程的 run()和 start()有什么区别?

  1. 每个线程都是通过某个特定Thread对象所对应的方法run()来完成其操作的,run()方法称为线程体。通过调用Thread类的start()方法来启动一个线程。
  2. start() 方法用于启动线程,run() 方法用于执行线程的运行时代码。run() 可以重复调用,而 start()只能调用一次。
  3. start()方法来启动一个线程,真正实现了多线程运行。调用start()方法无需等待run方法体代码执行完毕,可以直接继续执行其他的代码; 此时线程是处于就绪状态,并没有运行。 然后通过此Thread类调用方法run()来完成其运行状态, run()方法运行结束, 此线程终止。然后CPU再调度其它线程。
  4. run()方法是在本线程里的,只是线程里的一个函数,而不是多线程的。 如果直接调用run(),其实就相当于是调用了一个普通函数而已,直接待用run()方法必须等待run()方法执行完毕才能执行下面的代码,所以执行路径还是只有一条,根本就没有线程的特征,所以在多线程执行时要使用start()方法而不是run()方法。

为什么我们调用 start() 方法时会执行 run() 方法,为什么我们不能直接调用run() 方法?

  1. new 一个线程Thread,线程进入新建状态;调用start(),会启动一个线程并使线程进入就绪状态,当分配到时间片就可以开始工作了,start()会执行线程的相应准备工作,然后自动执行run()方法的内容,这是真正的多线程工作。
  2. 而直接执行 run() 方法,会把 run 方法当成一个 main 线程下的普通方法去执行,并不会在某个线程中执行它,所以这并不是多线程工作。

调用 start 方法方可启动线程并使线程进入就绪状态,而 run 方法只是 thread 的一个普通方法调用,还是在主线程里执行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/617146.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python基础知识:整理11 模块的导入、自定义模块和安装第三方包

1 模块的导入 1.1 使用import 导入time模块&#xff0c;使用sleep功能&#xff08;函数&#xff09; import time print("start") time.sleep(3) print("end")1.2 使用from 导入time的sleep功能 from time import sleep print("start") slee…

高级分布式系统-第6讲 分布式系统的容错性--可靠的组通信

可靠的组通信 组内通信最好是每个进程之间都建立点到点的通信&#xff0c; 但实际中这样的组织结构不是有效的&#xff0c; 因为会浪费很大的通信带宽。 在平等组中&#xff0c; 多播是主要的组织结构。 但多播是具有同步性质的容错结构&#xff0c; 并不适用拜占庭模型。 多…

每日算法打卡:饮料换购 day 12

文章目录 原题链接题目描述输入格式输出格式数据范围输入样例&#xff1a;输出样例&#xff1a; 题目分析示例代码 原题链接 1216. 饮料换购 题目难度&#xff1a;简单 题目来源&#xff1a;第六届蓝桥杯省赛C A/C组,第六届蓝桥杯省赛Java B组 题目描述 乐羊羊饮料厂正在举…

LeetCode刷题笔记

面试经典150题 1. 数组/字符串 1.1 合并两个有序数组 题目 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中&#xff0c;使合并后的数组同样按 非递减顺…

kotlin-运算符

区间运算符 闭区间运算符 a不能大于b var rang 1..9for(num in rang){print("${num}") //输出123456789}半开区间运算符 半开区间运算符a until b 用于定义一个从a~b(包括a边界值&#xff0c;但不包含b边界值)的所有值的区间&#xff0c;a不能大于b var rang 1 …

spring Data Elasticsearch入门

1.Elasticsearch Elasticsearch提供了两种连接方式&#xff1a; transport&#xff1a;通过TCP方式访问ES。&#xff08;已废弃&#xff09; rest&#xff1a;通过HTTP API 方式访问ES。 描述&#xff1a; Spring Data Elasticsearch 项目提供了与Elasticsearch 搜索引擎的集成…

17. 电话号码的字母组合(回溯)

从第一个数字开始遍历其对应的字母&#xff0c;将其加入StringBuffer中&#xff0c;继续深度优先搜索&#xff0c;当访问到最后一个数字的时候&#xff0c;将StringBuffer存储到ans中&#xff0c;然后回溯到下一个对应字母。 class Solution {public List<String> lette…

instanceof、对象类型转化、static关键字

instanceof 与 对象类型转换 instanceof是判断一个对象是否与一个类有关系的关键字 先看引用类型&#xff0c;再看实际类型 *例子&#xff1a;obj instanceof A 先看obj的类型是否与A有关联&#xff0c;无关联则报错&#xff0c;有关联则判断obj的实际类型 因为obj的实际类…

系分笔记数据库反规范化、SQL语句和大数据

文章目录 1、概要2、反规范化3、大数据4、SQL语句5、总结 1、概要 数据库设计是考试重点&#xff0c;常考和必考内容&#xff0c;本篇主要记录了知识点&#xff1a;反规范化、SQL语句及大数据。 2、反规范化 数据库遵循范式的设计&#xff0c;使得多表查询和连接表查询较多的时…

【面试突击】网关系统面试实战

&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308; 欢迎关注公众号&#xff08;通过文章导读关注&#xff1a;【11来了】&#xff09;&#xff0c;及时收到 AI 前沿项目工具及新技术 的推送 发送 资料 可领取 深入理…

基于JAVA+ssm开发的中草药智能采购管理系统设计与实现【附源码】

基于JAVAssm开发的中草药智能采购管理系统设计与实现【附源码】 &#x1f345; 作者主页 央顺技术团队 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; &#x1f345; 文末获取源码联系方式 &#x1f4dd; 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.…

C++中的常见数据结构 --- 队列、栈、列表

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 队列、栈、列表 前言一、队列&#xff08;Queue&#xff09;二、栈&#xff08;Stack&#xff09;三、列表&#xff08;List&#xff09;总结 前言 队列、栈、列表是其中三个…

stable diffusion代码学习笔记

前言&#xff1a;本文没有太多公式推理&#xff0c;只有一些简单的公式&#xff0c;以及公式和代码的对应关系。本文仅做个人学习笔记&#xff0c;如有理解错误的地方&#xff0c;请指出。 本文包含stable diffusion入门文献和不同版本的代码。 文献资源 本文学习的代码&…

Android基于Matrix绘制PaintDrawable设置BitmapShader,以手指触点为中心显示原图像圆图,Kotlin(2)

Android基于Matrix绘制PaintDrawable设置BitmapShader&#xff0c;以手指触点为中心显示原图像圆图&#xff0c;Kotlin&#xff08;2&#xff09; 在 https://zhangphil.blog.csdn.net/article/details/135374279 基础上&#xff0c;增加一个功能&#xff0c;当手指在上面的图片…

【DevOps-08-3】Jenkins容器内部使用Docker

一、简要描述 构建镜像和发布镜像到harbor都需要使用到docker命令。而在Jenkins容器内部安装Docker官方推荐直接采用宿主机带的Docker即可。 设置Jenkins容器使用宿主机Docker。 二、配置和操作步骤 1、修改宿主机docker.sock权限 # 修改docker.sock 用户和用户组都为root $ …

并发,并行,线程与UI操作

并行和并发是计算机领域中两个相关但不同的概念。 并行&#xff08;Parallel&#xff09;指的是同时执行多个任务或操作&#xff0c;它依赖于具有多个处理单元的系统。在并行计算中&#xff0c;任务被分成多个子任务&#xff0c;并且这些子任务可以同时在不同的处理单元上执行…

工智能基础知识总结--聚类算法

什么是聚类算法 聚类是一种机器学习技术,它涉及到数据点的分组。给定一组数据点,我们可以使用聚类算法将每个数据点划分为一个特定的组。理论上,同一组中的数据点应该具有相似的属性和/或特征,而不同组中的数据点应该具有高度不同的属性和/或特征。聚类是一种无监督学习的方…

DEJA_VU3D - Cesium功能集 之 112-获取圆节点(1)

前言 编写这个专栏主要目的是对工作之中基于Cesium实现过的功能进行整合,有自己琢磨实现的,也有参考其他大神后整理实现的,初步算了算现在有差不多实现小140个左右的功能,后续也会不断的追加,所以暂时打算一周2-3更的样子来更新本专栏(每篇博文都会奉上完整demo的源代码…

2024年甘肃省职业院校技能大赛信息安全管理与评估 样题二 模块二

竞赛需要完成三个阶段的任务&#xff0c;分别完成三个模块&#xff0c;总分共计 1000分。三个模块内容和分值分别是&#xff1a; 1.第一阶段&#xff1a;模块一 网络平台搭建与设备安全防护&#xff08;180 分钟&#xff0c;300 分&#xff09;。 2.第二阶段&#xff1a;模块二…

探索“城堡世界”APP:你的城堡,你的故事

在快节奏的现代生活中&#xff0c;我们常常渴望有一个属于自己的世界&#xff0c;可以随心所欲地创造和讲述故事。今天&#xff0c;我们要为大家介绍的是一款名为“城堡世界”的APP&#xff0c;它将带给你实现这个梦想的机会。 “城堡世界”是一款独特的APP&#xff0c;它允许用…