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

文章目录

  • 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结束循环

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【InternLM实战营第二期笔记】06:Lagent AgentLego 智能体应用搭建

文章目录 讲解为什么要有智能体什么是 Agent智能体的组成智能体框架AutoGPTReWooReAct Lagent & Agent LegoAgentLego 实操Lagent Web Demo自定义工具 AgentLego&#xff1a;组装智能体“乐高”直接使用作为智能体&#xff0c;WebUI文生图测试 Agent 工具能力微调 讲解 为…

立创EDA专业版设置位号居中并调整字体大小

选择某一个器件位号&#xff0c;右键->查找&#xff1a; 选择查找全部&#xff1a; 下面会显示查找结果&#xff1a; 查看&#xff0c;所有的位号都被选中了&#xff1a; 然后布局->属性位置&#xff1a; 属性位置选择中间&#xff1a; 然后位号就居中了 调整字体大小&a…

wooyun_2015_110216-Elasticsearch-vulfocus

1.原理 ElasticSearch具有备份数据的功能&#xff0c;用户可以传入一个路径&#xff0c;让其将数据备份到该路径下&#xff0c;且文件名和后缀都可控。 所以&#xff0c;如果同文件系统下还跑着其他服务&#xff0c;如Tomcat、PHP等&#xff0c;我们可以利用ElasticSearch的备…

使用 Scapy 库编写 TCP FIN 洪水攻击脚本

一、介绍 TCP FIN洪水攻击是一种分布式拒绝服务攻击&#xff08;DDoS&#xff09;&#xff0c;攻击者通过向目标服务器发送大量伪造的TCP FIN&#xff08;终止&#xff09;数据包&#xff0c;使目标服务器不堪重负&#xff0c;无法正常处理合法请求。FIN包通常用于关闭一个TCP…

【web本地存储】storage事件,StorageEvent对象介绍

storage事件 Web Storage API 内建了一套事件通知机制&#xff0c;当存储区域的内容发生改变&#xff08;包括增加、修改、删除数据&#xff09;时&#xff0c;就会自动触发storage事件&#xff0c;并把它发送给所有感兴趣的监听者&#xff0c;因此&#xff0c;如果需要跟踪存…

接口测试时, 数据Mock为何如此重要?

一、为什么要mock 工作中遇到以下问题&#xff0c;我们可以使用mock解决&#xff1a; 1、无法控制第三方系统某接口的返回&#xff0c;返回的数据不满足要求 2、某依赖系统还未开发完成&#xff0c;就需要对被测系统进行测试 3、有些系统不支持重复请求&#xff0c;或有访问…

三石峰汽车生产厂的设备振动检测项目案例

汽车生产厂的设备振动检测项目 ----天津三石峰科技&#xff08;http://www.sange-cbm.com&#xff09; 汽车产线有很多传动设备需要长期在线运行&#xff0c;会出现老化、疲劳、磨损等问题&#xff0c;为了避免意外停机造成损失&#xff0c;需要加装一些健康监测设备&#xf…

计算机组成刷题一轮(包过版)

搭配食用 计算机组成原理一轮-CSDN博客 目录 一、计算机系统概述 选择 计算机系统组成 冯诺依曼机 软件和硬件的功能 CPU等概念 计算机系统的工作原理 机器字长 运行速度 求MIPS 编译程序 机器语言程序 平均CPI和CPU执行时间 综合应用 存储程序原理 二…

圆 高级题目

上边的文章发了圆的初级题目&#xff0c;这篇来发高级 参考答案&#xff1a;ACCBBBBCDC

拓扑排序-java

主要通过宽度优先搜索&#xff08;BFS&#xff09;来实现有向无环图的拓扑序列&#xff0c;邻接表存储图。数组模拟单链表、队列&#xff0c;实现BFS基本操作。 文章目录 前言 一、有向图的拓扑序列 二、算法思路 1.拓扑序列 2.算法思路 三、使用步骤 1.代码如下&#xff08;示…

Java实现数据结构——顺序表

目录 一、前言 二、实现 2.1 增 2.2 删 2.3 查 2.4 改 2.5 销毁顺序表 三、Arraylist 3.1 构造方法 3.2 常用操作 3.3 ArrayList遍历 四、 ArrayList具体使用 4.1 杨辉三角 4.2 简单洗牌算法 一、前言 笔者在以前的文章中实现过顺序表 本文在理论上不会有太详细…

上汽集团25届暑期实习测评校招笔试题库已发(真题)

&#x1f4e3;上汽集团 25届暑期实习测评已发&#xff0c;正在申请的小伙伴看过来哦&#x1f440; ㊙️本次实习项目面向2025届国内外毕业生&#xff0c;开放了新媒体运营、销售策略、市场运营、物流、质量分析等岗位~ ✅测评讲解&#xff1a; &#x1f449;测评自收到起需在…

利用streamlit结合langchain_aws实现claud3的页面交互

测试使用的代码如下 import streamlit as st from langchain_aws import ChatBedrockdef chat_with_model(prompt, model_id):llm ChatBedrock(credentials_profile_name"default", model_idmodel_id, region_name"us-east-1")res llm.invoke(prompt)re…

市值超越苹果,英伟达的AI崛起与天润融通的数智化转型

Agent&#xff0c;开启客户服务新时代。 世界商业格局又迎来一个历史性时刻。 北京时间6月6日&#xff0c;人工智能芯片巨头英伟达&#xff08;NVDA&#xff09;收涨5.16%&#xff0c;总市值达到3.01万亿美元&#xff0c;正式超越苹果公司&#xff0c;成为仅次于微软&#xf…

C++ 命名空间|缺省参数|函数重载

一、命名空间 1.什么是命名空间 命名空间&#xff08;namespace&#xff09;是C中的一种机制&#xff0c;用来解决不同代码库之间的命名冲突问题。 先来看一个例子&#xff1a; #include <iostream>void print() {std::cout << "Hello from print()"…

Polar Web【简单】upload

Polar Web【简单】upload Contents Polar Web【简单】upload思路EXPPythonGo 运行&总结 思路 如题目所说&#xff0c;本题考查的是文件上传漏洞的渗透技巧。 打开环境&#xff0c;发现需要上传的是图片文件&#xff0c;故考虑使用截取数据包进行数据修改进行重放。在重发器…

Java面向对象-方法的重写、super

Java面向对象-方法的重写、super 一、方法的重写二、super关键字1、super可以省略2、super不可以省略3、super修饰构造器4、继承条件下构造方法的执行过程 一、方法的重写 1、发生在子类和父类中&#xff0c;当子类对父类提供的方法不满意的时候&#xff0c;要对父类的方法进行…

蓝牙安全入门——两道CTF题目复现

文章目录 蓝牙安全入门题目 low_energy_crypto获取私钥解密 题目 蓝牙钥匙的春天配对过程配对方法密钥分发数据加密安全漏洞和保护实际应用实际应用 蓝牙安全入门 &#x1f680;&#x1f680;最近一直对车联网比较感兴趣&#xff0c;但是面试官说我有些技术栈缺失&#xff0c;所…

一文带你轻松掌握Java数组定义和声明

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/掘金/腾讯云&#xff1b;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一…

【Redis】解决 Redis 运行在 Protected Mode 下的 DENIED 错误:消除 Redis 受保护模式的完美方案

【Redis】解决 Redis 运行在 Protected Mode 下的 DENIED 错误&#xff1a;消除 Redis 受保护模式的完美方案 大家好 我是寸铁&#x1f44a; 总结了一篇【Redis】解决 Redis 运行在 Protected Mode 下的 DENIED 错误&#xff1a;消除 Redis 受保护模式的完美方案✨ 喜欢的小伙伴…