【Java面试】十六、并发篇:线程基础

news2024/10/7 18:20:39

文章目录

  • 1、进程和线程的区别
  • 2、并行和并发的区别
  • 3、创建线程的四种方式
    • 3.1 Runnable和Callable创建线程的区别
    • 3.2 线程的run和start
  • 4、线程的所有状态与生命周期
  • 5、新建T1、T2、T3,如何保证线程的执行顺序
  • 6、notify和notifyAll方法有什么区别
  • 7、wait方法和sleep方法有什么不同
  • 8、如何停止一个正在运行的线程
    • 8.1 使用退出标志
    • 8.2 调用stop方法
    • 8.3 调用interrupt方法

1、进程和线程的区别

在这里插入图片描述

  • 一个程序或者应用被运行,就是开启了一个进程(应用.exe背后的代码被从磁盘加载到内存)
  • 一个进程下,包含了多个线程,分别处理着不同的任务
  • 线程更轻量,上下文成本切换更低(上下文切换即从一个线程切换到另一个线程)

2、并行和并发的区别

  • 并行:多项工作一起执行,下班后,你收拾屋子,你对象做饭。与其相反的就是串行,即一步一步来,或者一件一件事情的做。(4核CPU同时执行4个线程)

在这里插入图片描述

  • 并发:多个工作换着处理,下班后,你屋子收拾一半后,去准备做饭,菜准备好后又回去接着收拾屋子(多个线程轮流使用一个或者多个CPU)

补充:操作系统中,有个任务调度器,将CPU时间片(比如15毫秒)分给不同的程序使用。CPU在线程间的切换速度很快,给人的感觉就是同时运行的。

在这里插入图片描述

并发是一个人同时吃三个馒头(一张嘴,第一个馒头吃一口,转身再吃一口第二个馒头),而并行是三个人同时吃三个馒头(三个人各吃各的,好比多核CPU各自执行指令)。

最后,并发在后端层面上,也指同一时刻,多个线程在访问同一个资源,多个线程对一个点,对应的例子: 春运抢票、电商秒杀

3、创建线程的四种方式

  • 继承Thread类

在这里插入图片描述

  • 实现Runnable接口

在这里插入图片描述

  • 实现Callable接口,Callable的泛型即重写的call方法的返回值类型

在这里插入图片描述

  • 线程池创建线程

在这里插入图片描述

3.1 Runnable和Callable创建线程的区别

  • Runnable 接口 run 方法没有返回值
  • Callable 接口 call 方法有返回值,是个泛型,和 Future、FutureTask配合可以用来获取异步执行的结果
  • Callable 接口的 call 方法允许抛出异常,而 Runnable 接口的run 方法的异常只能在内部try-catch消化,不能继续上抛

3.2 线程的run和start

  • start方法是用来启动线程的,通过该线程调用执行run方法,只能被调用一次
  • run方法里面封装了要被线程执行的代码,是一个普通方法,可以被调用多次
public class ThreadTest {
	public static void main(String[] args){
	
		Thread t1 = new Thread("t1") {
			@Override
			public void run() {
				System.out.println("running...");
			}
			
	};
	t1.run();
	t1.run();
	t1.start();
	t1.start();

}

调用两次run方法:
在这里插入图片描述
调用两次start方法:

在这里插入图片描述

4、线程的所有状态与生命周期

JDK源码中的线程状态枚举值:

在这里插入图片描述

状态流转:
  • NEW:新建状态,创建出一个Thread对象

  • Runnable:可执行状态,执行start方法,此时如果抢到了CPU时间片,那就去执行run方法,然后线程进入终止状态(死亡)

  • Blocked:没抢不到锁(lock、synchronized),进入阻塞状态,抢到锁后切换为Runnable状态

  • Waiting:调用了wait方法,进入等待状态,其他线程调用notify方法后被唤醒,进入Runnable状态
    在这里插入图片描述

  • Timed_Waiting:计时等待状态,线程调用了sleep方法,sleep时间过后进入Runnable状态

流转图:
在这里插入图片描述

5、新建T1、T2、T3,如何保证线程的执行顺序

thread.join();

以下,t2线程中执行t1.join,即等待t1线程执行完成后,再执行t2

在这里插入图片描述

6、notify和notifyAll方法有什么区别

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

如下,object对象上wait了两个线程t1、t2

在这里插入图片描述
notify时,只随机唤醒了一个object对象上wait的线程

在这里插入图片描述

7、wait方法和sleep方法有什么不同

共同点:

  • wait和sleep都会让当前线程暂时放弃CPU时间片的使用权,进入阻塞状态

不同点:

1)方法归属不同:

  • sleep是Thread类的静态方法
  • wait是Object类的静态方法,每个对象都有

2)醒来时机不同:

  • 执行sleep(long time) 和 wait(long time) 的线程,在相应毫秒过后会自己醒来进入就绪状态
  • wait(long time)wait() 都可以被 notify 唤醒,且wait() 如果不被唤醒就一直等待
  • sleep和wait都可以被打断唤醒

3)锁的特性不同:

  • 调用wait方法,必须先获取wait方法所在对象的锁,否则IllegalMonitorStateException,sleep则不用获取任何锁
  • wait对象执行后,会释放其占有的对象锁,其他线程可抢这个锁(放弃CPU时间片、放弃对象锁)
  • sleep如果是在synchronized代码块里,sleep并不会释放synchronized抢到的对象锁(放弃CPU时间片,如果有锁也不会放弃)

8、如何停止一个正在运行的线程

8.1 使用退出标志

加一个标记字段,改了标记之后,线程return,结束执行

class MyRun implements Runnable {
    boolean flag = false;
    public void run() {
        for (int i = 0; i < 100; i++) {
            if (! this.flag) {
                System.out.println(Thread.currentThread().getName() + "--->" + i);
                System.out.println(this.run);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                System.out.println("这是一些终止线程前要做的事");
                System.out.println("保存数据中..终止线程成功!");
                return;
            }
        }
    }
}
public class ThreadTest2 {
    public static void main(String[] args) {
        MyRun r = new MyRun();
        Thread t = new Thread(r);
        t.start();
        //sleep主线程三秒
        try{
            Thread.sleep(3000);
        }catch(InterruptedException e){
            e.printStackTrace();
        }
        //终止,改run属性为true
        r.run = true;

    }
}


在这里插入图片描述

8.2 调用stop方法

sleep方法已作废

MyThread myThread = new MyThread();
myThread.start();
//强制终止
myThread.stop();

8.3 调用interrupt方法

  • 打断正在阻塞的线程(sleep、wait、join),线程会抛出InterruptedException异常
public class MyInterrupt {

    public static void main(String[] args) throws InterruptedException {
    
        Thread t1 = new Thread(()->{
            System.out.println("t1 正在运行...");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "t1");
        t1.start();
        Thread.sleep(500);
        t1.interrupt();
        System.out.println(t1.isInterrupted());
        
    }
}

在这里插入图片描述

  • 打断正常线程,改变线程的中止标志位,是否退出由线程自己决定,思路上和方式一相似
public class MyInterrupt {

    public static void main(String[] args) throws InterruptedException {
    
        Thread t2 = new Thread(()->{
            while(true) {
                Thread current = Thread.currentThread();
                boolean interrupted = current.isInterrupted();
                if(interrupted) {
                    System.out.println("打断状态:"+ interrupted);
                    break;
                }
            }
        }, "t2");
        t2.start();
        Thread.sleep(500);
        t2.interrupt();

    }
}

如上,主线程中调用t2.interrupt(),t2线程的中止标志位变为true,但是否中止执行,看 t2 线程自己,上面t2线程自己判断标志位为true时,就break结束循环

在这里插入图片描述

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

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

相关文章

Django Forbidden (CSRF cookie not set.)解决办法

解决办法就是在setting.py文件中注释&#xff1a; django.middleware.csrf.CsrfViewMiddleware, 这个中间件是为了防止跨站请求伪造的&#xff0c;平时用网页表单请求时&#xff0c;post提交是没有问题的&#xff0c;但是用api调用时就会被禁止&#xff0c;为了能使用接口调用…

文件怎么去重?5个技巧,教你删除重复文件!

一般来说&#xff0c;在处理大量文件时&#xff0c;你可能会遇到重复的类似文件。这些文件占据了电脑上不必要的磁盘空间&#xff0c;导致系统性能下降。而这些文件可以是不同类型的&#xff0c;如照片、视频、音频、存档、文档等。正因如此&#xff0c;您需要通过文件去重来删…

(四)React组件、useState

1. 组件 1.1 组件是什么 概念&#xff1a;一个组件就是用户界面的一部分&#xff0c;它可以有自己的逻辑和外观&#xff0c;组件之间可以相互嵌套&#xff0c;也可以复用多次。 组件化开发可以让开发者像搭积木一样构建一个完整的庞大应用 1.2 React组件 在React中&#xf…

项目-五子棋双人对战:游戏房间的管理(5)

完整代码见: 邹锦辉个人所有代码: 测试仓库 - Gitee.com 之前我们已经实现了玩家匹配的功能, 我们都知道, 匹配完过后就可以进入游戏房间进行对战了, 所以我们下一步关注的重点就是对于游戏房间的管理. 模块详细讲解 功能需求 通过匹配的方式, 自动给玩家加入到一个游戏房间…

312. 戳气球

题目 有 n 个气球&#xff0c;编号为 0 到 n - 1&#xff0c;每个气球上都标有一个数字&#xff0c;这些数字存在数组 nums 中。 现在要求你戳破所有的气球。戳破第 i 个气球&#xff0c;你可以获得 nums[i - 1] * nums[i] * nums[i 1] 枚硬币。 这里的 i - 1 和 i 1 代表和…

vue 响应拦截器,针对某个接口的返回值做特殊处理

1、service.interceptors.response.use 接收两个参数&#xff1a; &#xff08;1&#xff09;参数一&#xff1a;接口成功的回调函数 &#xff08;2&#xff09;参数二&#xff1a;接口失败的回调函数 如要实现以下需求&#xff1a;匹配路径中包含 /api-special 的接口&…

Vue3【十四】watchEffect自动监视多个数据实现,不用明确指出监视哪个数据

Vue3【十四】watchEffect自动监视多个数据实现&#xff0c;不用明确指出监视哪个数据 Vue3【十四】watchEffect自动监视多个数据实现&#xff0c;不用明确指出监视哪个数据 进入立即执行一次&#xff0c;并监视数据变化 案例截图 目录结构 代码 Person.vue <template>&…

LabVIEW 与组态软件在自动化系统中的应用比较与选择

LabVIEW 确实在非标单机设备、测试和测量系统中有着广泛的应用&#xff0c;特别是在科研、教育、实验室和小型自动化设备中表现突出。然而&#xff0c;LabVIEW 也具备一定的扩展能力&#xff0c;可以用于更复杂和大型的自动化系统。以下是对 LabVIEW 与组态软件在不同应用场景中…

2002NOIP普及组真题 4. 过河卒

线上OJ 地址&#xff1a; 【02NOIP普及组】过河卒 核心思想&#xff1a; 对于此类棋盘问题&#xff0c;一般可以考虑 dp动态规划、dfs深搜 和 bfs广搜。 解法一&#xff1a;dp动态规划 方法&#xff1a;从起点开始逐步计算到达每个位置的路径数。对于每个位置&#xff0c;它…

7天搞定Python必背500单词

必备必记-你的Python就牛掰了 每天只背100个就足够了 老话说的好基础不扎实,地动山摇,在学习Python的时候前期基础很重要. 下面是大家常用遇到的Python基础单词,帮助你更好地掌握Python语言: 1.变量 在Python中用来存储数值,文本或其他信息的名称. 2. 函数 用于执行特定…

六、主存储器管理,计算机操作系统教程,第四版,左万利,王英

文章目录 [toc]一、存储管理的功能1.1 存储分配1.2 存储共享1.3 存储保护1.4 存储扩充1.5 地址映射 二、内存资源管理2.1 内存分区2.1.1 静态分区与动态分区2.1.2 等长分区与异长分区 2.2 内存分配2.2.1 静态等长分区的分配2.2.2 *动态异长分区的分配 2.3 碎片与紧凑 三、界地址…

Django 视图类

在Django框架中&#xff0c;视图类&#xff08;Class-based views&#xff0c;简称CBVs&#xff09;提供了一个面向对象的方式来定义视图。这种方式可以让你通过创建类来组织视图逻辑&#xff0c;而不是使用基于函数的视图&#xff08;Function-based views&#xff0c;简称FBV…

jmeter性能优化之mysql监控sql慢查询语句分析

接上次博客&#xff1a;基础配置 多用户登录并退出jmx文件&#xff1a;百度网盘 提取码&#xff1a;0000 一、练习jmeter脚本检测mysql慢查询 随意找一个脚本(多用户登录并退出)&#xff0c;并发数设置300、500后分别查看mysql监控平台 启动后查看&#xff0c;主要查看mysql…

探索ChatGPT-4在解决化学知识问题上的研究与应用

1. 概述 近年来&#xff0c;人工智能的发展主要集中在 GPT-4 等大型语言模型上。2023 年 3 月发布的这一先进模型展示了利用广泛知识应对从化学研究到日常问题解决等复杂挑战的能力。也开始进行研究&#xff0c;对化学的各个领域&#xff0c;从化学键到有机化学和物理化学&…

xstream运用,JAVA对象转xml,xml转JAVA对象

目录 xstream 优点&#xff1a; 缺点&#xff1a; XStream的应用场景 用到的依赖 代码实现 xml标签对应的实体类 Header Package Request Response TradeInfo 工具类 XmlUtils 执行结果 xstream XStream是一个Java类库&#xff0c;主要用于将对象序列化为XML&#xf…

【零基础一看就会】Python爬虫从入门到应用(下)

目录 一、urllib的学习 1.1 urllib介绍 1.2 urllib的基本方法介绍 urllib.Request &#xff08;1&#xff09;构造简单请求 &#xff08;2&#xff09;传入headers参数 &#xff08;3&#xff09;传入data参数 实现发送post请求&#xff08;示例&#xff09; response.…

dnf手游版游玩感悟

dnf手游于5月21号正式上线&#xff0c;作为一个dnf端游老玩家&#xff0c;并且偶尔上线ppk&#xff0c;自然下载了手游版&#xff0c;且玩了几天。 不得不说dnf手游的优化做到了极好的程度。 就玩法系统这块&#xff0c;因为dnf属于城镇地下城模式&#xff0c;相比…

C\C++内存管理(未完结)

文章目录 一.C\C内存分布二.C语言中动态内存管理方式&#xff1a;malloc/calloc/realloc/free三.C内存管理方式3.1.new/delete操作内置类型3.2.new和delete操作自定义类型 四.operator new与operator delete函数&#xff08;重要点进行讲解&#xff09;4.1. operator new与oper…

Spring Security 应用详解

一、 集成SpringBoot 1.1 Spring Boot 介绍 Spring Boot 是一套 Spring 的快速开发框架&#xff0c;基于 Spring 4.0 设计&#xff0c;使用 Spring Boot 开发可以避免一些繁琐的工程 搭建和配置&#xff0c;同时它集成了大量的常用框架&#xff0c;快速导入依赖包&#xff0…

【SpringCloud学习笔记】Docker(中篇)

Docker 1. 自定义镜像 前面我们都是使用docker pull拉取仓库中现成的镜像&#xff0c;但是如果我们想要将一个Java应用程序构建成镜像然后部署应该怎么做呢&#xff1f;这个时候我们就需要自定义镜像了 **镜像&#xff1a;**本质上就是一堆文件的集合&#xff0c;包含了应用程…