Java多线程:初识多线程!左手画方,右手画圆

在这里插入图片描述

  • 👑专栏内容:Java
  • ⛪个人主页:子夜的星的主页
  • 💕座右铭:前路未远,步履不停

目录

  • 一、线程与进程
  • 二、创建线程方法
    • 1、继承`Thread`类
    • 2、实现`Runnable`接口
    • 3、两者区别
    • 4、举个栗子
    • 5、简洁写法
      • Ⅰ、`Thread`匿名内部类写法
      • Ⅱ、`Runnable`匿名内部类写法
      • Ⅲ、使用`Lambda`表达式


嗨!想象一下,你的面前有一张展开的白纸,而你的左手和右手各握一支画笔。你的任务是在同一时间,左手画出一个方形,右手画出一个圆形。你觉得这能够完成吗?我相信大多数人会认为这是不可能完成的任务。因为我们的大脑是单线程的,一次只能专注于一项任务,一心二用在绝大多数情况下是不可行的。然而,计算机不同,它具备多线程编程的能力,可以同时处理多个任务。现在,让我们一起探索Java中多线程这个神奇的功能吧。
在这里插入图片描述

一、线程与进程

进程是计算机中执行中的程序的实例。它是操作系统进行管理和调度的基本单位

线程,有时被称为轻量级进程,是程序中的一个单独的执行流。它是操作系统调度的最小单位。与进程相比,线程之间的上下文切换通常更为迅速和高效。一个线程就是一个 “执行流”。每个线程之间都可以按照顺讯执行自己的代码、多个线程之间 “同时” 执行着多份代码。

  • 进程是操作系统能独立调度的最小单位,而线程是进程中可并发执行的单元;
  • 一个应用程序至少包括1个进程,而1个进程包括1个或多个线程;
  • 每个进程在执行过程中拥有独立的内存单元,而一个进程的多个线程在执行过程中共享内存。

图片描述

那我们来简单的类比一下吧!

image-20230818164204908
计算机的CPU就像一个工厂,而进程就是工厂里面的车间线程就是车间里面的工人

我们能够发现,多核CPU对应多个工厂,这些工厂可以从事不同的生产任务。比如有炼铁的、炼油的、食品加工等等。在一个工厂中,又可以包含一个或多个车间(进程),但是由于电力资源有限,同一时间就只能有一个车间在运行。换句话说,对于单核CPU,同一时间只能处理一个进程,其他进程处在等待状态。而一个车间中,可以有一个或多个工人(线程)协同工作,他们共享内部资源,共同完成任务。

同一个进程中,这些线程共用同一份资源(内存 + 硬盘…),但是每个线程独立去CPU上调度(状态、上下文、优先级、记账信息…)各自有各自的一份

所以,进程是操作系统进行分配的基本单位。而线程是操作系统进行调度执行的基本单位。
在这里插入图片描述
【面试题】谈谈进程和线程的区别和联系

  • 进程是包含线程的,都是实现并发编程的方式,但是线程比进程更轻量。

  • 进程是系统分配资源的基本单位,线程是系统调度的基本单位。创建进程的时候,把分配资源(虚拟地址空间、文件描述符表)的工作给做了,后面创建线程,直接共用资源即可。

  • 进程有独立的地址空间,彼此之间不会相互影响到,进程的独立性。多个线程共用这份地址空间,一个线程一旦抛出异常,就可能会导致进程异常结束。

  • 进程和进程之间不共享内存空间,同一个进程的线程之间共享同一个内存空间。

image-20230818211422931
在这里插入图片描述

二、创建线程方法

在 Java 中,有两种创建多线程的方式,分别是继承 Thread 类和实现 Runnable 接口。下面让我们一起来学习下这两种创建多线程的方法吧。

1、继承Thread

class Mythread extends Thread{
    public void run() {
        System.out.println("这是线程运行代码!");
    }
}

public class Main {
    public static void main(String[] args) {
    
        Mythread mythread = new Mythread();
        mythread.start();
    }
}

创建一个类,继承 Thread ,重写run方法,该方法包含线程的实际执行逻辑。

start()方法:start() 方法是Thread类的一个方法,它用于启动线程并调用线程的run()方法。
在这个例子中,myThread.start() 会启动一个新的线程,并在新线程中执行 run() 方法中定义的代码。

如果把myThread.start();改成myThread.run();后,运行的结果也是hello world。这两个有什么不一样呢?

run只是上面的入口方法,并没有调用系统api也没有创建真正的线程来。

图片描述

2、实现Runnable接口

class Myrunnable implements Runnable{
    public void run() {
        System.out.println("这是线程运行代码!");
    }
}

public class Main {
    public static void main(String[] args) {

        Thread thread = new Thread(new Myrunnable());
        thread.start();
    }
}

该方法主要是创建一个类,实现 Runnable 接口,重写run方法。

3、两者区别

Thread这里是直接把要完成的工作,放到了ThreadRun方法中

Runnable这里,则是分开了,把要完成的工作放到了Runnable中,再让RunnableThread配合。

把线程要执行的任务和线程本身进一步解耦合了。并发编程中,来完成某个工作,使用Runnable描述这个工作的具体细节。这样使用多线程的方式,就可以使用Runnable来搭配线程使用。使用线程池的方式,就可以使用Runnable来搭配线程池使用,使用协议的方式,也可以使用Runnable搭配协程。

特征继承 Thread实现 Runnable 接口
类的继承关系直接继承 Thread 类。类实现 Runnable 接口,可以继承其他类。
创建方式创建类的子类,重写 run() 方法。创建类,实现 Runnable 接口,实现 run() 方法。
多线程对象创建直接创建线程对象的实例。先创建 Runnable 对象,再通过 Runnable 对象创建 Thread 对象。
启动线程直接调用 start() 方法。调用 Thread 类的构造方法,传递 Runnable 对象,然后调用 start() 方法。
资源共享较难实现资源共享。更容易实现资源共享,因为可以共享同一个 Runnable 对象。
多态使用难以使用多态,因为已经继承了 Thread 类。更容易使用多态,因为类可以继续实现其他接口或继承其他类。

4、举个栗子

回到上面的问题。把myThread.start();改成myThread.run();后,运行的结果也是hello world。
这两个有什么不一样呢?我们来举个栗子看看吧。

图片描述

class MyThread extends Thread{
    @Override
    public void run() {
        while(true){
            System.out.println("hello thread");
        }
    }
}
public class Demo1 {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();
        //myThread.run();
        while(true){
            System.out.println("hello main");
        }
    }
}

image-20230818223628990
使用myThread.start();运行的程序,会同时打印hello thread 和 hello main

两个循环都在执行,两个线程分别执行自己的循环,并发性的执行。

而使用myThread.run();运行的程序,只会打印hello main

只执行了一个循环。

在这里插入图片描述

5、简洁写法

我们可以通过匿名内部类来ThreadRunnable这两种写法。
什么是匿名内部类?

匿名内部类是一种在声明和创建类的对象同时进行的特殊形式,它没有显式的类名称。这种方式通常用于在使用类的地方定义类的实例,尤其是在创建接口的实现或继承抽象类的实例时。

Ⅰ、Thread匿名内部类写法

    public static void main(String[] args) {
        Thread thread = new Thread(){
            @Override
            public void run() {
                System.out.println("这是线程运行代码!");
            }
        };
        thread.start();
    }

图片描述

在这里插入图片描述

Ⅱ、Runnable匿名内部类写法

    public static void main(String[] args) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
            System.out.println("这是线程运行代码!");
            }
        });
        thread.start();
    }

在这里插入图片描述

图片描述

Ⅲ、使用Lambda表达式

Lambda表达式主要用于实现函数式接口,Lambda表达式本质上就是一个匿名函数,像这样的匿名函数可以做回调函数来使用。

图片描述

匿名函数,就是没有命名的函数。它具有传递函数体的能力,却无需提前声明整个函数的结构。

回调函数则是在程序执行中,不需要程序员主动调用的函数。相反,它会在特定的时机或条件下,由系统或其他代码自动触发执行。程序员通过将函数传递给其他代码,实现了一种回调机制,使得在适当的时候,这个函数会被调用,完成特定的操作。

好了,废话不多说,先用Lambda表达式写一下吧。

    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            System.out.println("这是线程运行代码!");
        });
        thread.start();
    }

Thread thread = new Thread(() -> {
这里使用Lambda表达式创建了一个新的Thread对象,构造方法接受一个Runnable接口的实现作为参数。Lambda表达式的内容在大括号中,用于定义线程运行时执行的代码块。

图片描述

线程的创建并不是只有这五种写法,还可以用线程池和Callable写法。这个我们后面再聊!

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

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

相关文章

Django(七)

Django(六) 4.编辑用户 点击编辑,跳转到编辑页面(将编辑行的ID携带过去)。编辑页面(默认数据,根据ID获取并设置到页面中)提交: 错误提示数据校验在数据库更新 user_edit.html {% exte…

php 字符串常用函数

目录 1.一些常用函数 2.代码示例 1.一些常用函数 函数名描述trim()删除字符串两端空行或其它预定义符rtrim()删除字符串右边空行或其它预定义符ltrim()删除字符串左边空行或其它预定义符dirname()返回路径中的目录部分str_split()把字符串分割到数组里explode()使用一个字符串…

2024,传统鞋服的“高端梦”该醒了

文 | 螳螂观察 作者 | 图霖 “一千块都不要的波司登,宝贝们还不冲吗?” 入夜,一位身着羽绒服的美女主播在灯火通明的直播间正声嘶力竭地反复呐喊。 一群不知是托还是真实消费者的用户在评论区敲出自己的身高体重,想从主播那得…

给定n个字符串s[1...n], 求有多少个数对(i, j), 满足i < j 且 s[i] + s[j] == s[j] + s[i]?

题目 思路&#xff1a; 对于字符串a&#xff0c;b, (a.size() < b.size()), 考虑对字符串b满足什么条件&#xff1a; 由1、3可知a是b的前后缀&#xff0c;由2知b有一个周期是3&#xff0c;即a.size()&#xff0c;所以b是用多个a拼接而成的&#xff0c;有因为a是b的前后缀&…

基于Java SSM框架实现雁门关风景区宣传网站项目【项目源码】计算机毕业设计

基于java的SSM框架实现雁门关风景区宣传网站演示 Java技术 Java技术它是一个容易让人学会和使用的一门服务器语言。它在编程的过程当中只需要很少的知识就能建立起一个真正的交互站点。对于这个教程来说它并不需要你完全去了解这种语言&#xff0c;只要能快速融入web站点就可以…

基于博弈树的开源五子棋AI教程[3 极大极小搜索]

基于博弈树的开源五子棋AI教程[3 极大极小搜索] 引子极大极小搜索原理alpha-beta剪枝负极大搜索尾记 引子 极大极小搜索是博弈树搜索中最常用的算法&#xff0c;广泛应用于各类零和游戏中&#xff0c;例如象棋&#xff0c;围棋等棋类游戏。算法思想也是合乎人类的思考逻辑的&a…

【100个 Unity实用技能】☀️ | UGUI中 判断屏幕中某个坐标点的位置是否在指定UI区域内

&#x1f3ac; 博客主页&#xff1a;https://xiaoy.blog.csdn.net &#x1f3a5; 本文由 呆呆敲代码的小Y 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f384; 学习专栏推荐&#xff1a;Unity系统学习专栏 &#x1f332; 游戏制作专栏推荐&#xff1a;游戏制作 &…

MySQL的事务机制

一、事务机制简述 事务机制,避免写入直接操作数据文件&#xff1b;利用日志来实现间接写入&#xff0c;与事务有关的, redo日志与undo日志&#xff1b;sql语句操作记录复制到undo日志然后增删改查操作的结果会记录在redo日志&#xff0c;如果操作没有什么问题就把数据同步到数…

C语言基础语法跟练 day3

31、不使用累计乘法的基础上&#xff0c;通过移位运算&#xff08;<<&#xff09;实现2的n次方的计算。 #include <stdio.h> int main() {int i 0;scanf("%d",&i);printf("%d",1<<i);return 0; } 32、问题&#xff1a;一年约有 3.…

C++基础算法之枚举

星光不问赶路人 岁月不负有心人 &#x1f3a5;烟雨长虹&#xff0c;孤鹜齐飞的个人主页 &#x1f525;个人专栏 期待小伙伴们的支持与关注&#xff01;&#xff01;&#xff01; 目录 枚举算法的简介 枚举算法的运用 #特别数的和 题目描述# 输入描述# 输入输出样例# #找到最多…

Linux下安装JET2

0. 说明&#xff1a; JET2是一个基于Joint Evolutionary Trees的利用序列和结构信息预测蛋白质界面的软件&#xff0c;详情见: http://www.lcqb.upmc.fr/JET2/JET2.html&#xff0c;http://www.lgm.upmc.fr/JET/JET.html 和 https://doi.org/10.1371/journal.pcbi.1004580 本…

2024年前端面试中JavaScript的30个高频面试题之中级知识

基础知识 高级知识 13. 什么是闭包?闭包的用例有哪些? 闭包是一个功能,它允许函数捕获定义该函数的环境(或保留对作用域中变量的访问)即使在该作用域已经关闭后。 我们可以说闭包是函数和词法环境的组合,其中定义了该函数。 换句话说,闭包为函数提供了访问自己的作用域、…

vulnhub靶场之DC-5

一.环境搭建 1.靶场描述 DC-5 is another purposely built vulnerable lab with the intent of gaining experience in the world of penetration testing. The plan was for DC-5 to kick it up a notch, so this might not be great for beginners, but should be ok for p…

深度学习笔记(四)——TF2构建基础网络常用函数+简单ML分类网络实现

文中程序以Tensorflow-2.6.0为例 部分概念包含笔者个人理解&#xff0c;如有遗漏或错误&#xff0c;欢迎评论或私信指正。 截图和程序部分引用自北京大学机器学习公开课 TF2基础常用函数 1、张量处理类 强制数据类型转换&#xff1a; a1 tf.constant([1,2,3], dtypetf.floa…

鸿蒙开发环境搭建-高频环境问题解决

1.Node版本问题 由于SDK的部分工具依赖Node.js运行时&#xff0c;推荐使用配套API版本的Node.js&#xff0c;保证工程的兼容性。 匹配关系见下表&#xff1a; API LevelNode.js支持范围API Level≤914.x&#xff08;≥14.19.1&#xff09;、16.xAPI Level>914.x&#xff0…

Linux tail命令详解和高级用法举例

目 录 一、概述 二、tail命令解释 1&#xff0e;命令格式; 2&#xff0e;功能 3&#xff0e;选项 4&#xff0e;选项的基本用法 &#xff08;1&#xff09; 显示行号 &#xff08;2&#xff09;忽略指定字符数 &#xff08;3&#xff09; 不显示文件名 三…

小白进公司快速熟悉环境和代码的方法

1.企业开发模式 企业开发模式里&#xff0c;我们的项目模块可能非常多此时我们是不能将所有模块都拉取到本地的&#xff0c;主要原因如下&#xff1a; 我们很可能并没有全部工程代码的权限 微服务集群部署非常复杂&#xff0c;本地部署成本太高 微服务模块众多&#xff0c;本…

NAND Separate Command Address (SCA) 接口命令解读

CA output packet和CA input packet是Separate Command Address (SCA) NAND接口协议中用于命令和地址传输的关键数据结构。 CA Input Packet: 在SCA接口中&#xff0c;输入到NAND器件的命令和地址信息被组织成并行至串行转换的CA&#xff08;Command and Address&#xff09;输…

装机必看:电脑Bios里的CSM兼容模块是啥?打开有啥用?

前言 最近朋友装了一台新的电脑&#xff0c;用的i5-13490f的CPU。但是由于预算有限&#xff0c;手边只有一块GTX650ti&#xff0c;没办法&#xff0c;只好先这么用着了。 谁知道出现了个大问题&#xff1a;电脑开机居然没办法显示。 由于电脑所有的配件基本上都是全新的&…

查看SQL Server的表字段类型、长度、描述以及是否可为null

文章目录 初步理解小步测试组合一下参考文章有更详细评述 继续理解得到大部分信息 本文参考&#xff1a;https://blog.csdn.net/josjiang1/article/details/80558068。 也可以直接点击这里文章链接&#xff1a; sql server查询表结构&#xff08;字段名&#xff0c;数据类型&a…