深入浅出Java多线程

系列文章目录


文章目录

  • 系列文章目录
  • 前言
  • 一、多线程基础概念介绍
    • 线程的状态转换图
    • 线程的调度
    • 一些常见问题
  • 二、Java 中线程的常用方法介绍
  • Java语言对线程的支持
  • Thread常用的方法
  • 三、线程初体验(编码示例)


前言

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。
在这里插入图片描述


一、多线程基础概念介绍

进程是程序(任务)的执行过程,它持有资源(共享内存,共享文件)和线程。

分析:

① 执行过程 是动态性的,你放在电脑磁盘上的某个eclipse或者QQ文件并不是我们的进程,只有当你双击运行可执行文件,使eclipse或者QQ运行之后,这才称为进程。它是一个执行过程,是一个动态的概念。

② 它持有资源(共享内存,共享文件)和线程:我们说进程是资源的载体,也是线程的载体。这里的资源可以理解为内存。我们知道程序是要从内存中读取数据进行运行的,所以每个进程获得执行的时候会被分配一个内存。

③ 线程是什么?
在这里插入图片描述
如果我们把进程比作一个班级,那么班级中的每个学生可以将它视作一个线程。学生是班级中的最小单元,构成了班级中的最小单位。一个班级有可以多个学生,这些学生都使用共同的桌椅、书籍以及黑板等等进行学习和生活。

在这个意义上我们说:

线程是系统中最小的执行单元;同一进程中可以有多个线程;线程共享进程的资源。

④ 线程是如何交互?

就如同一个班级中的多个学生一样,我们说多个线程需要通信才能正确的工作,这种通信,我们称作线程的交互。

⑤ 交互的方式:互斥、同步

类比班级,就是在同一班级之内,同学之间通过相互的协作才能完成某些任务,有时这种协作是需要竞争的,比如学习,班级之内公共的学习资料是有限的,爱学习的同学需要抢占它,需要竞争,当一个同学使用完了之后另一个同学才可以使用;如果一个同学正在使用,那么其他新来的同学只能等待;另一方面需要同步协作,就好比班级六一需要排演节目,同学需要齐心协力相互配合才能将节目演好,这就是进程交互。

##一个线程的生命周期
线程经过其生命周期的各个阶段。下图显示了一个线程完整的生命周期。
在这里插入图片描述
新建状态:
使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。

就绪状态:
当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。

运行状态:
如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。

阻塞状态:
如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。

死亡状态:
一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。

线程的状态转换图

在这里插入图片描述
1、新建状态(New):新创建了一个线程对象。
2、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
3、运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
(一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
(二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
(三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
5、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

线程的调度

1、调整线程优先级:

每一个Java线程都有一个优先级,这样有助于操作系统确定线程的调度顺序。

Java线程的优先级用整数表示,取值范围是1~10,Thread类有以下三个静态常量:

static int MAX_PRIORITY
线程可以具有的最高优先级,取值为10。
static int MIN_PRIORITY
线程可以具有的最低优先级,取值为1。
static int NORM_PRIORITY
分配给线程的默认优先级,取值为5。

Thread类的setPriority()和getPriority()方法分别用来设置和获取线程的优先级。
每个线程都有默认的优先级。主线程的默认优先级为Thread.NORM_PRIORITY。
线程的优先级有继承关系,比如A线程中创建了B线程,那么B将和A具有相同的优先级。
JVM提供了10个线程优先级,但与常见的操作系统都不能很好的映射。如果希望程序能移植到各个操作系统中,应该仅仅使用Thread类有以下三个静态常量作为优先级,这样能保证同样的优先级采用了同样的调度方式。
具有较高优先级的线程对程序更重要,并且应该在低优先级的线程之前分配处理器资源。但是,线程优先级不能保证线程执行的顺序,而且非常依赖于平台。

2、线程睡眠:Thread.sleep(long millis)方法,使线程转到阻塞状态。millis参数设定睡眠的时间,以毫秒为单位。当睡眠结束后,就转为就绪(Runnable)状态。sleep()平台移植性好。

3、线程等待:Object类中的wait()方法,导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 唤醒方法。这个两个唤醒方法也是Object类中的方法,行为等价于调用 wait(0) 一样。

4、线程让步:Thread.yield() 方法,暂停当前正在执行的线程对象,把执行机会让给相同或者更高优先级的线程。

5、线程加入:join()方法,等待其他线程终止。在当前线程中调用另一个线程的join()方法,则当前线程转入阻塞状态,直到另一个进程运行结束,当前线程再由阻塞转为就绪状态。

6、线程唤醒:Object类中的notify()方法,唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的,并在对实现做出决定时发生。线程通过调用其中一个 wait 方法,在对象的监视器上等待。 直到当前的线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争;例如,唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。类似的方法还有一个notifyAll(),唤醒在此对象监视器上等待的所有线程。

注意:Thread中suspend()和resume()两个方法在JDK1.5中已经废除,不再介绍。因为有死锁倾向。

7、常见线程名词解释
主线程:JVM调用程序main()所产生的线程。
当前线程:这个是容易混淆的概念。一般指通过Thread.currentThread()来获取的进程。
后台线程:指为其他线程提供服务的线程,也称为守护线程。JVM的垃圾回收线程就是一个后台线程。
前台线程:是指接受后台线程服务的线程,其实前台后台线程是联系在一起,就像傀儡和幕后操纵者一样的关系。傀儡是前台线程、幕后操纵者是后台线程。由前台线程创建的线程默认也是前台线程。可以通过isDaemon()和setDaemon()方法来判断和设置一个线程是否为后台线程。

一些常见问题

1、线程的名字,一个运行中的线程总是有名字的,名字有两个来源,一个是虚拟机自己给的名字,一个是你自己的定的名字。在没有指定线程名字的情况下,虚拟机总会为线程指定名字,并且主线程的名字总是main,非主线程的名字不确定。
2、线程都可以设置名字,也可以获取线程的名字,连主线程也不例外。
3、获取当前线程的对象的方法是:Thread.currentThread();
4、每个线程都将启动,每个线程都将运行直到完成。一系列线程以某种顺序启动并不意味着将按该顺序执行。对于任何一组启动的线程来说,调度程序不能保证其执行次序,持续时间也无法保证。
5、当线程目标run()方法结束时该线程完成。
6、一旦线程启动,它就永远不能再重新启动。只有一个新的线程可以被启动,并且只能一次。一个可运行的线程或死线程可以被重新启动。
7、线程的调度是JVM的一部分,在一个CPU的机器上上,实际上一次只能运行一个线程。一次只有一个线程栈执行。JVM线程调度程序决定实际运行哪个处于可运行状态的线程。
众多可运行线程中的某一个会被选中做为当前线程。可运行线程被选择运行的顺序是没有保障的。
8、尽管通常采用队列形式,但这是没有保障的。队列形式是指当一个线程完成“一轮”时,它移到可运行队列的尾部等待,直到它最终排队到该队列的前端为止,它才能被再次选中。事实上,我们把它称为可运行池而不是一个可运行队列,目的是帮助认识线程并不都是以某种有保障的顺序排列唱呢个一个队列的事实。
9、尽管我们没有无法控制线程调度程序,但可以通过别的方式来影响线程调度的方式。

二、Java 中线程的常用方法介绍

Java语言对线程的支持

  主要体现在Thread类和Runnable接口上,都继承于java.lang包。它们都有个共同的方法:public void run()。

run方法为我们提供了线程实际工作执行的代码。

下表列出了Thread类的一些重要方法:
在这里插入图片描述
测试线程是否处于活动状态。 上述方法是被Thread对象调用的。下面的方法是Thread类的静态方法。

在这里插入图片描述

Thread常用的方法

在这里插入图片描述

三、线程初体验(编码示例)

创建线程的方法有两种:

1.继承Thread类本身

2.实现Runnable接口

线程中的方法比较有特点,比如:启动(start),休眠(sleep),停止等,多个线程是交互执行的(cpu在某个时刻。只能执行一个线程,当一个线程休眠了或者执行完毕了,另一个线程才能占用cpu来执行)因为这是cpu的结构来决定的,在某个时刻cpu只能执行一个线程,不过速度相当快,对于人来将可以认为是并行执行的。

在一个java文件中,可以有多个类(此处说的是外部类),但只能有一个public类。

这两种创建线程的方法本质没有任何的不同,一个是实现Runnable接口,一个是继承Thread类。

使用实现Runnable接口这种方法:

1.可以避免java的单继承的特性带来的局限性;

2.适合多个相同程序的代码去处理同一个资源情况,把线程同程序的代码及数据有效的分离,较好的体现了面向对象的设计思想。开发中大多数情况下都使用实现Runnable接口这种方法创建线程。

实现Runnable接口创建的线程最终还是要通过将自身实例作为参数传递给Thread然后执行

语法: Thread actress=new Thread(Runnable target ,String name);

例如: Thread actressThread=new Thread(new Actress(),“Ms.runnable”);

actressThread.start();

代码示例:

package com.study.thread;

public class Actor extends Thread{
    public void run() {
        System.out.println(getName() + "是一个演员!");
        int count = 0;
        boolean keepRunning = true;

        while(keepRunning){
            System.out.println(getName()+"登台演出:"+ (++count));
            if(count == 100){
                keepRunning = false;
            }
            if(count%10== 0){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println(getName() + "的演出结束了!");
    }

    public static void main(String[] args) {
       Thread actor = new Actor();//向上转型:子类转型为父类,子类对象就会遗失和父类不同的方法。向上转型符合Java提倡的面向抽象编程思想,还可以减轻编程工作量
       actor.setName("Mr. Thread");
       actor.start();

       //调用Thread的构造函数Thread(Runnable target, String name)
       Thread actressThread = new Thread(new Actress(), "Ms. Runnable");
       actressThread.start();
    }

}
//注意:在“xx.java”文件中可以有多个类,但是只能有一个Public类。这里所说的不是内部类,都是一个个独立的外部类
class Actress implements Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "是一个演员!");//Runnable没有getName()方法,需要通过线程的currentThread()方法获得线程名称
        int count = 0;
        boolean keepRunning = true;

        while(keepRunning){
            System.out.println(Thread.currentThread().getName()+"登台演出:"+ (++count));
            if(count == 100){
                keepRunning = false;
            }
            if(count%10== 0){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println(Thread.currentThread().getName() + "的演出结束了!");
    }

}

/**
 *运行结果Mr. Thread线程和Ms. Runnable线程是交替执行的情况
 *分析:计算机CPU处理器在同一时间同一个处理器同一个核只能运行一条线程,
 *当一条线程休眠之后,另外一个线程才获得处理器时间
 */

运行结果:
在这里插入图片描述
示例2:

ArmyRunnable 类:

package com.study.threadTest1;

/**
 * 军队线程
 * 模拟作战双方的行为
 */
public class ArmyRunnable implements Runnable {

    /* volatile关键字
     * volatile保证了线程可以正确的读取其他线程写入的值
     * 如果不写成volatile,由于可见性的问题,当前线程有可能不能读到这个值
     * 关于可见性的问题可以参考JMM(Java内存模型),里面讲述了:happens-before原则、可见性
     * 用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的值
     */
    volatile boolean keepRunning = true;

    @Override
    public void run() {
        while (keepRunning) {
            //发动5连击
            for(int i=0;i<5;i++){
                System.out.println(Thread.currentThread().getName()+"进攻对方["+i+"]");
                //让出了处理器时间,下次该谁进攻还不一定呢!
                Thread.yield();//yield()当前运行线程释放处理器资源
            }
        }
        System.out.println(Thread.currentThread().getName()+"结束了战斗!");
    }

}

KeyPersonThread 类:

package com.study.threadTest1;


public class KeyPersonThread extends Thread {
    public void run(){
        System.out.println(Thread.currentThread().getName()+"开始了战斗!");
        for(int i=0;i<10;i++){
            System.out.println(Thread.currentThread().getName()+"左突右杀,攻击隋军...");
        }
        System.out.println(Thread.currentThread().getName()+"结束了战斗!");
    }

}

Stage 类:

1 package com.study.threadTest1;
 2 
 3 /**
 4  * 隋唐演义大戏舞台 6  */
 7 public class Stage extends Thread {
 8     public void run(){
 9         System.out.println("欢迎观看隋唐演义");
10         //让观众们安静片刻,等待大戏上演
11         try {
12             Thread.sleep(5000);
13         } catch (InterruptedException e1) {
14             e1.printStackTrace();
15         }
16         System.out.println("大幕徐徐拉开");
17 
18         try {
19             Thread.sleep(5000);
20         } catch (InterruptedException e1) {
21             e1.printStackTrace();
22         }
23 
24         System.out.println("话说隋朝末年,隋军与农民起义军杀得昏天黑地...");
25         ArmyRunnable armyTaskOfSuiDynasty = new ArmyRunnable();
26         ArmyRunnable armyTaskOfRevolt = new ArmyRunnable();
27 
28         //使用Runnable接口创建线程
29         Thread  armyOfSuiDynasty = new Thread(armyTaskOfSuiDynasty,"隋军");
30         Thread  armyOfRevolt = new Thread(armyTaskOfRevolt,"农民起义军");
31 
32         //启动线程,让军队开始作战
33         armyOfSuiDynasty.start();
34         armyOfRevolt.start();
35 
36         //舞台线程休眠,大家专心观看军队厮杀
37         try {
38             Thread.sleep(50);
39         } catch (InterruptedException e) {
40             e.printStackTrace();
41         }
42 
43         System.out.println("正当双方激战正酣,半路杀出了个程咬金");
44 
45         Thread  mrCheng = new KeyPersonThread();
46         mrCheng.setName("程咬金");
47         System.out.println("程咬金的理想就是结束战争,使百姓安居乐业!");
48 
49         //停止军队作战
50         //停止线程的方法
51         armyTaskOfSuiDynasty.keepRunning = false;
52         armyTaskOfRevolt.keepRunning = false;
53 
54         try {
55             Thread.sleep(2000);
56         } catch (InterruptedException e) {
57             e.printStackTrace();
58         }
59         /*
60          * 历史大戏留给关键人物
61          */
62         mrCheng.start();
63 
64         //万众瞩目,所有线程等待程先生完成历史使命
65         try {
66             mrCheng.join();//join()使其他线程等待当前线程终止
67         } catch (InterruptedException e) {
68             e.printStackTrace();
69         }
70         System.out.println("战争结束,人民安居乐业,程先生实现了积极的人生梦想,为人民作出了贡献!");
71         System.out.println("谢谢观看隋唐演义,再见!");
72     }
73 
74     public static void main(String[] args) {
75         new Stage().start();
76     }
77 
78 }

运行结果:

在这里插入图片描述

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

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

相关文章

LeeCode热题100(爬楼梯)

爬楼梯这个题我断断续续看了不下5遍&#xff0c;哪次看都是懵逼的&#xff0c;就会说是满足动态规划&#xff0c;满足斐波那契数列&#xff0c;也不说为什么。 本文一定让你明白怎么分析这个题的规律&#xff08;利用数学的递推思想来分析&#xff09;&#xff0c;看不懂来打我…

SleepFM:利用对比学习预训练的多模态“睡眠”基础模型

大模型技术论文不断&#xff0c;每个月总会新增上千篇。本专栏精选论文重点解读&#xff0c;主题还是围绕着行业实践和工程量产。若在阅读过程中有些知识点存在盲区&#xff0c;可以回到如何优雅的谈论大模型重新阅读。另外斯坦福2024人工智能报告解读为通识性读物。若对于如果…

Go微服务: 封装nacos-sdk-go的v2版本与应用

概述 基于前文&#xff1a;https://active.blog.csdn.net/article/details/139213323我们基于此SDK提供的API封装一个公共方法来用于生产环境 封装 nacos-sdk-go 我们封装一个 nacos.go 文件, 这个是通用的工具库 package commonimport ("fmt""github.com/nac…

如何查看谁连接到了你的Wi-Fi网络?这里提供几种方法或工具

序言 你知道谁连接到你路由器的Wi-Fi网络吗?查看从路由器或计算机连接到Wi-Fi网络的设备列表,找出答案。 请记住,现在很多设备都可以连接到了你的Wi-Fi,该名单包括笔记本电脑、智能手机、平板电脑、智能电视、机顶盒、游戏机、Wi-Fi打印机等。 使用GlassWire Pro查看连接…

蒙自源六一童趣献礼:纯真餐单,唤醒你的童年味蕾

当岁月的车轮滚滚向前&#xff0c;我们总会怀念那些逝去的时光&#xff0c;尤其是那段纯真无瑕的童年。当六一儿童节来临&#xff0c;心底的那份童趣与回忆总会被轻轻触动。从5月25日起&#xff0c;蒙自源旗下各大门店为所有小朋友&#xff0c;以及那些心怀童真的大人们&#x…

Mac vm虚拟机激活版:VMware Fusion Pro for Mac支持Monterey 1

相信之前使用过Win版系统的朋友们对这款VMware Fusion Pro for Mac应该都不会陌生&#xff0c;这款软件以其强大的功能和适配能力广受用户的好评&#xff0c;在Mac端也同样是一款最受用户欢迎之一的虚拟机软件&#xff0c;VM虚拟机mac版可以让您能够轻松的在Apple的macOS和Mac的…

华为交换机、路由器配置查询、用户界面常见配置及安全加固

华为交换机、路由器配置查询、用户界面常见配置及安全加固。 一、查询命令 1.常用的查询命令 查看当前生效的配置信息&#xff1a; display current-configuration //正在生效的配置&#xff0c;默认参数不显示。查看当前视图下生效的配置信息&#xff1a; display this //常…

数字IC基础:主要的FPGA厂商

相关阅读 数字IC基础https://blog.csdn.net/weixin_45791458/category_12365795.html?spm1001.2014.3001.5482 Xilinx&#xff08;现已被AMD收购&#xff09; Xilinx, 成立于1984年&#xff0c;是FPGA&#xff08;现场可编程门阵列&#xff09;技术的创始者和市场领导者。该公…

Mac下载Homebrew

通过command空格搜索终端打开 直接输入 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 然后输入电脑密码 然后直接回车等待安装完成 注意⚠️&#xff1a;如果出现报错/opt/homebrew/bin is not in your PATH…

python操作mongodb底层封装并验证pymongo是否应该关闭连接

一、pymongo简介 github地址&#xff1a;https://github.com/mongodb/mongo-python-driver mymongo安装命令&#xff1a;pip install pymongo4.7.2 mymongo接口文档&#xff1a;PyMongo 4.7.2 Documentation PyMongo发行版包含Python与MongoDB数据库交互的工具。bson包是用…

【设计模式深度剖析】【1】【行为型】【模板方法模式】| 以烹饪过程为例加深理解

&#x1f448;️上一篇:结构型设计模式对比 文章目录 模板方法模式定义英文原话直译如何理解呢&#xff1f; 2个角色类图代码示例 应用优点缺点使用场景 示例解析&#xff1a;以烹饪过程为例类图代码示例 模板方法模式 模板方法模式&#xff08;Template Method Pattern&…

生信分析进阶4 - 比对结果的FLAG和CIGAR信息含义与BAM文件指定区域提取

BAM文件时存储比对数据的常用格式&#xff0c;可用于短reads和长reads数据。BAM是二进制压缩格式&#xff0c;SAM文件为其纯文本格式&#xff0c;CRAM为BAM的高压缩格式&#xff0c;IO效率相比于BAM略差&#xff0c;但是占用存储空间更小。 1. BAM文件的比对信息 BAM的核心信…

软件测试期末复习

第四章 边界黑盒测试续 4.3边界值设计方法 1.边界值设计方法&#xff1a;故障往往出现在定义域或边界值上。通常边界值分析法是作为对等价类划分法的补充。其测试用例来自等价类的边界。是对输入或输出的边界值进行测试的一种黑盒测试方法。 2.边界值分析法和等价类划分法的…

在Visual Studio2022中同一个项目里写作业,有多个cpp文件会报错

为了省事&#xff0c;在同一个项目里写很多个题目&#xff0c;结果只有一个cpp文件时没出错&#xff0c;写了2个cpp文件再想运行时就出错了&#xff1b; 将不相关的cpp文件移出去 在源文件中对其点击右键&#xff0c;找到“从项目中排除”&#xff1b; 结果如图&#xff0c;剩…

网络原理-三

一、连接管理 建立连接,断开连接 建立连接,TCP有连接的. 客户端执行 socket new Socket(SeverIP,severPort); -> 这个操作就是在建立连接. 上述只是调用socket api,真正建立连接的过程,实在操作系统内核完成的. 内核是怎样完成上述的 " 建立连接 "过程的…

云硬盘的基准性能测试场景

参考来源&#xff1a; 深入浅出云计算-05 | 云硬盘&#xff1a;云上IO到底给不给力 云硬盘的性能等级 当下的云硬盘经过了多次的软硬件迭代&#xff0c;尤其是SSD的迅速发展&#xff0c;吞吐量和随机读写能力等各项性能指标都已经不再是问题了。在现代云计算中&#xff0c;已…

数仓建模—ChatETL

数仓建模—ChatETL 前面我们介绍过ChatBI ,就是让用户通过自然语言对话的方式可以获取到自己想要的数据,然后通过合适的报表展示出来,其实我们可以将其理解为应用层面的技术创新,但是这个实现的前提就是我们底层已经有加工好的大量的数据模型数据表,并且有完善的元数据建…

“论SOA在企业集成架构设计中的应用”必过模板,突击2024软考高项论文

考题部分 企业应用集成(Enterprise Application Integration, EAI)是每个企业都必须要面对的实际问题。面向服务的企业应用集成是一种基于面向服务体系结构(Service-OrientedArchitecture,SOA&#xff09;的新型企业应用集成技术&#xff0c;强调将企业和组织内部的资源和业务功…

【自动化运维】不要相信人,把所有的东西都交给机器去处理

不积跬步&#xff0c;无以至千里&#xff1b;不积小流&#xff0c;无以成江海。 大家好&#xff0c;我是闲鹤&#xff0c;十多年开发、架构经验&#xff0c;先后在华为、迅雷服役过&#xff0c;也在高校从事教学3年&#xff1b;目前已创业了7年多&#xff0c;主要从事物联网/车…

【网络安全的神秘世界】MySQL

&#x1f31d;博客主页&#xff1a;泥菩萨 &#x1f496;专栏&#xff1a;Linux探索之旅 | 网络安全的神秘世界 | 专接本 MySQL MySQL 教程 | 菜鸟教程 (runoob.com) 什么是数据库 数据库&#xff08;Database&#xff09;是按照数据结构来组织、存储和管理数据的仓库 在do…