多线程的五种“打开”方式

1 概念

1.1 线程是什么??

线程(Thread)是计算机科学中的一个基本概念,它是进程(Process)中的一个执行单元,负责执行程序的指令序列。线程是操作系统能够进行调度和执行的最小单位。在多任务操作系统中,多个线程可以在同一个进程内并发执行,共享进程的资源。

{

假设你正在厨房中准备晚餐,这个过程中有多个线程在运行,每个线程代表一个不同的烹饪任务。这些线程可以同时执行,以加速整个烹饪过程,就像多线程在计算机程序中一样。

  1. 主厨线程:这个线程负责协调整个烹饪过程。主厨线程制定了食谱和指导其他线程如何协同工作。

  2. 切菜线程:这个线程负责将食材切成适当的大小和形状。它可以在切菜板上进行多个切割任务,以提高效率。

  3. 炉灶线程:这个线程负责在炉灶上烹饪不同的菜肴。例如,一个线程可以煮汤,另一个线程可以煎肉,它们可以同时工作,以节省时间。

  4. 烤箱线程:如果你需要烤一道菜,那么烤箱线程可以负责在烤箱中烘烤食物,同时其他线程继续处理其他任务。

  5. 洗碗线程:一旦完成烹饪,就有一个线程负责洗碗和清理厨房。这个线程可以与其他线程并发运行,以确保整个晚餐流程的顺利结束。

在这个例子中,每个线程都代表一个不同的烹饪任务,它们可以并行工作,以提高烹饪效率,就像多线程在计算机程序中允许不同任务并发执行一样

}

1.2  为什么要使用线程??

1 “并发编程”成为“刚需”

        单核CPU的发展遇到了瓶颈,想要提高算力,就需要多核CPU。而并发编程能够充分利用多核CPU资源;

        有些任务场景需要“等待IO”,为了让等待的时间去做一些其他工作,也需要使用到并发编程。

2. 虽然进程也能够实现并发编程,但是线程比进程更加轻量级。

  • 创建线程比创建进程更快.
  • 销毁线程比销毁进程更快.
  • 调度线程比调度进程更快.

1.3 进程和线程的区别??

  • 进程是包含线程的。每个进程至少有一个线程的存在,也就是主线程;
  • 进程和线程之间不共享内存空间。同一个进程的线程之间共享同一内存空间;
  • 进程是系统分配资源的最小单位,线程是操作系统调度的最小单位;
  • 进程是相互独立的,一个进程的崩溃通常不会影响其他进程。线程之间更密切相关,一个线程的错误可能会影响到同一进程中的其他线程。
  • 创建和销毁进程通常比线程昂贵,因为进程需要分配和释放独立的内存空间和资源。线程的创建和销毁通常更快,因为它们共享进程的资源,不需要分配独立的内存空间。

1.4 Java的线程和操作系统的线程的区别??

  • 线程是操作系统中的概念. 操作系统内核实现了线程这样的机制, 并且对用户层提供了一些 API 供用户使用(例如 Linux pthread ).
  • Java 标准库中 Thread 类可以视为是对操作系统提供的 API 进行了进一步的抽象和封装.

2 感受多线程代码

多线程和普通程序最大的区别就是每个线程都是独立的执行流 多线程之间是并发执行的。

public class ThreadDemo {
    private static class MyThread extends Thread{
        @Override
        public void run() {
            Random random = new Random();
            while (true){
                // 打印主线程名称
                System.out.println(Thread.currentThread().getName());
                try {
                    Thread.sleep(random.nextInt(10));//随机停止运行0-9秒
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        MyThread t3 = new MyThread();

        //启动并创建线程工作
        t1.start();
        t2.start();
        t3.start();

        //主线程工作
        Random random = new Random();
        while (true){
            // 打印主线程名称
            System.out.println(Thread.currentThread().getName());
            try {
                Thread.sleep(random.nextInt(10));//随机停止运行0-9秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}

结果:

我们可以使用JDK提供的jconsole命令观察线程(在jdk的bin目录下面)

3 创建线程的“五种”方式

方法1 继承Thread类

public class ThreadDemo1 {

    static class MyThread extends Thread{
        //重写run方法  run描述该线程要干的活是什么
        @Override
        public void run() {
            System.out.println("我是一个线程 hello thread!");
        }
        //run方法执行完毕后 新的这个线程就会被销毁
    }

    public static void main(String[] args) {
        Thread thread = new MyThread();//thread类不需要任何包??为什么还有哪些我们见过的 出现这种情况 java.lang包下面的是不用导包的 比如string stirngbuilder
        thread.start();//线程中的启动方法 start创建了一个新线程 有新线程来执行run方法
    }
}

方法2 实现Runnable 接口

// Runnable 作用就是描述一个“要执行的任务” run方法就是任务的执行细节
class MyRunnable implements Runnable{

    @Override
    public void run() {
        System.out.println("hello thread-runnable");
    }
}

public class ThreadDemo2 {
    public static void main(String[] args) {
        // new Runnable就是描述一个任务
        MyRunnable runnable = new MyRunnable();
        //然后将这个任务交给线程来执行
        Thread thread = new Thread(runnable);
        thread.start();
        thread.run();
        /*
        * thread.run()是在当前线程中执行线程的任务,没有创建新的线程,不实现并发。
        thread.start()创建一个新的线程,并在新线程中执行线程的任务,实现了多线程并发。通常应该使用thread.start()来启动线程*/
    }
}

首先对比一下上面两种方法:

  • 继承 Thread , 直接使用 this 就表示当前线程对象的引用.
  • 实现 Runnable 接口, this 表示的是 MyRunnable 的引用. 需要使用 Thread.currentThread()

后面的方法都是前两者的“变形”:

方法3 匿名内部类创建 Thread 子类对象

//使用匿名内部类来实现线程
public class ThreadDemo3 {
    public static void main(String[] args) {
        Thread t = new Thread() {
            @Override
            public void run() {
                System.out.println("匿名内部类实现thread");
            }
        };
        t.start();
    }
}

方法4 匿名内部类创建 Runnable 子类对象

//使用匿名内部类
public class ThreadDemo4 {
    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("实现runnable-匿名内部类");
            }
        });
        t.start();
    }
}

方法5 lambda 表达式创建 Runnable 子类对象

//lambda
public class ThreadDemo5 {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            System.out.println("hello thread");
        });
        t.start();
    }
}

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

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

相关文章

MariaDB数据库服务器

目录 一、什么是数据库? 二、什么是关系型数据库? 三、数据库字符集和排序规则是什么? 四、常用数据类型 五、Mariadb数据库相关配置案例 一、什么是数据库? 数据库(DB)是以一定方式长期存储在计算机硬盘内…

PHP8内置函数中的数学函数-PHP8知识详解

php8中提供了大量的内置函数,以便程序员直接使用常见的内置函数包括数学函数、变量函数、字符串函数、时间和日期函数等。今天介绍内置函数中的数学函数。 本文讲到了数学函数中的随机数函数rand()、舍去法取整函数floor()、向上取整函数 ceil()、对浮点数进行四舍…

1.频偏估计算法

目录 整数倍频偏估计方法 小数倍频偏估计方法 使用CP进行频偏估计 使用SSB进行频偏估计 OFDM对频偏比较敏感,频偏会影响子载波的正交性,造成载波间干扰。频偏对PRACH相关计算峰值的影响本质上是子载波间干扰导致的。时域检测:首先对接收…

聚合多个电商API接口平台

API接口测试(点击免费测试) 随着数字化商业时代的到来,API接口已成为电商资源连接利器,也是全球传统互联网企业转型的基础。 2021年 Google Cloud 研究显示,全球互联网企业近3/4的企业持续投入数字化转型&#xff0c…

最佳实践:TiDB 业务读变慢分析处理

作者:李文杰 网易游戏计费 TiDB 负责人 在使用或运维管理 TiDB 的过程中,大家几乎都遇到过 SQL 变慢的问题,尤其是查询相关的读变慢问题。读变慢的问题大部分情况下都遵循一定的规律,通过经验的积累可以快速的定位和优化&#xff…

【倒着考虑】CF Edu 21 D

Problem - D - Codeforces 题意: 思路: 这道题需要倒着步骤考虑,就是先去假设已经分为了两部分,这左右两部分的和相等,然后去想上一个步骤 倒着一个步骤后,可以发现这样的性质: Code&#xf…

C++:初识类与this指针

文章目录 前言一、类类的定义和实例化类的访问限定符类的作用域计算类的大小 二、类的成员函数的this指针总结 个人主页 : 个人主页 个人专栏 : 《数据结构》 《C语言》《C》 前言 一、类 类的定义和实例化 注意类定义结束时后面分号( ; )不能省略。 类…

【算法刷题-栈与队列篇】

目录 1.leetcode-232. 用栈实现队列2.leetcode-225. 用队列实现栈3.leetcode-20. 有效的括号(1)代码1(2)代码2 4.leetcode-1047. 删除字符串中的所有相邻重复项5.leetcode-150. 逆波兰表达式求值6.leetcode-239. 滑动窗口最大值7.…

关于一个git的更新使用流程

1.第一步使用git bash 使用git bash命令来进行操作(当然我是个人比较喜欢用这种方法的) 2. 第二步:连接 3.第三步:进入 4.第四步:查看分支 5.第五步:切换分支 将本地文件更新后之后进行提交 6.第六步&am…

猫头虎博主赠书一期:《Kubernetes原生微服务开发》

🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…

【力扣 第 360 场周赛】题解(一题待补)

目录 2833. 距离原点最远的点2834. 找出美丽数组的最小和2835. 使子序列的和等于目标的最少操作次数TODO 2836. 在传球游戏中最大化函数值 这场比赛排名第 1 - 1000 名的参赛者 可获「NIO 蔚来」简历内推机会,比有的场次前十才给容易多了。 2833. 距离原点最远的点…

计算机/嵌入式入门教材资料

背景 自学计算机,首先我们要找到好的教材、教程,可以事半功倍。 目前,互联网上计算机资源较多,难的不再是寻找资源,而是筛选出质量比较高的资源。 基于笔者经验,推荐以下资源。 书籍 传统的书籍是纸质版…

C语言:三子棋小游戏

简介: 目标很简单:实现一个 三子棋小游戏。三子棋大家都玩过,规则就不提及了。本博文中实现的三子棋在对局中,电脑落子是随机的,不具有智能性,玩家的落子位置使用键盘输入坐标。下面开始详细介绍如何实现一…

基于RabbitMQ的模拟消息队列之二---创建项目及核心类

一、创建项目 创建一个SpringBoot项目,环境:JDK8,添加依赖:Spring Web、MyBatis FrameWork(最主要) 二、创建核心类 1.项目分层 2.核心类 在mqserver包中添加一个包,名字为core,表示核心类…

前端Vue自定义得分构成水平柱形图组件 可用于系统专业门类得分评估分析

引入Vue自定义得分构成水平柱形图组件:cc-horBarChart 随着技术的发展,传统的开发方式使得系统的复杂度越来越高,一个小小的改动或小功能的增加可能会导致整体逻辑的修改,造成牵一发而动全身的情况。为了解决这个问题&#xff0c…

设计模式系列-创建者模式

一、上篇回顾 上篇我们主要讲述了抽象工厂模式和工厂模式。并且分析了该模式的应用场景和一些优缺点,并且给出了一些实现的思路和方案,我们现在来回顾一下: 抽象工厂模式:一个工厂负责所有类型对象的创建,支持无缝的新增新的类型对…

centos安装jdk-8u371-linux-x64.tar.gz包

java -version //查看jdk版本 rpm -qa | grep jdk 删除带有"openjdk"字样的jdk 例: rpm -e --nodeps java-1.7.0-openjdk-1.7.0.141-2.6.10.5.el7.x86_64 下载该版本的jdk(jdk-8u371-linux-x64.tar.gz) (https://www.oracle.com/java/technologies/javase/javase8u2…

linux 内存一致性

linux 出现内存一致性的场景 1、编译器优化 ,代码上下没有关联的时候,因为编译优化,会有执行执行顺序不一致的问题(多核单核都会出现) 2、多核cpu乱序执行,cpu的乱序执行导致内存不一致(多核出…

MATLAB制图代码【第二版】

MATLAB制图代码【第二版】 文档描述 Code describtion: This code is version 2 used for processing the data from the simulation and experiment. Time : 2023.9.3 Author: PEZHANG 这是在第一版基础上,迭代出的第二版MATLAB制图代码,第二版的特点是…

kvm 虚拟机添加网卡方法

找到kvm虚拟机的配置文件 虚拟机名称.xml kvm虚拟机配置文件默认路径&#xff1a;/etc/libvirt/qemu/ 先停kvm虚拟机 virsh shutdown 虚拟机名称 修改kvm虚拟机配置文件 virsh edit 虚拟机名称 在kvm虚拟机里面配置新增接口如下内容&#xff1a; <interface typebridg…