创建线程的两种方式

news2024/10/9 21:25:06

一、线程相关概念

  • 程序:完成特定任务,用某种语言编写的一组指令的集合。
  • 进程:运行起来的程序就是进程。进程运行时,操作系统需要为该进程分配内存空间。进程是一个动态过程,有产生、存在和消亡的过程。
  • 线程:线程是由进程创建的,是进程的一个实体,一个进程可以拥有多个线程。
  • 单线程:同一时刻只允许执行一个线程。
  • 多线程:同一个时刻,可以执行多个线程,比如:一个QQ进程,可以同时打开多个聊天窗口,一个迅雷进程,可以同时下载多个文件。
  • 并发:单核CPU实现的多任务就是并发
  • 并行:同一个时刻,多个任务同时执行,多核CPU可以实现并行。

通过下面这段代码可以显示您当前电脑的处理器CPU的个数。

public class CpuNum {
    public static void main(String[] args) {
        Runtime runtime = Runtime.getRuntime();
        int cpuNums = runtime.availableProcessors();
        System.out.println("当前电脑有cpu个数:" + cpuNums);
    }
}

二、线程的基本使用

创建线程有两种方法:1.继承Thread类;2.实现Runnable接口。
实现多线段的两种方法

2.1 继承Thread类创建线程

继承Thread类之后需要重写run方法,写上自己的代码逻辑。继承了Thread类之后,可以通过创建该对象,调用其的start()方法来启动线程,启动之后会自动执行run方法中的代码。这里举个例子:创建一个猫咪线程,每秒打印一次“喵喵,我是小喵咪 x”。

public class ThreadTest1 {
    public static void main(String[] args) throws InterruptedException {
        new Cat().start();//启动猫咪线程
        //当main线程启动一个子线程 Thread-0,主线程不会阻塞,会继续执行

        System.out.println("主线程继续执行 " + Thread.currentThread().getName());
        for (int i = 0; i < 10; i++) {
            System.out.println("主线程" + i);
            Thread.sleep(1000);
        }
    }
}

//1. 当一个类继承了Thread类,该类就可以当做线程使用
//2. 我们会重写run方法,写上自己业务代码
//3. Thread类里面的run方法是继承Runnable接口的run方法

class Cat extends Thread{
    int times = 0;
    @Override
    public void run() {//重写run方法,写上自己的业务
        while (true) {
            System.out.println("喵喵, 我是小猫咪" + times
                    + "线程名 = " + Thread.currentThread().getName());
            ++times;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            if(times == 8){
                break;//退出while循环,结束线程
            }
        }
    }
}

主线程可以创建很多子线程,只有当所有子线程都结束时,进程才会结束。

思考:为何线程启动时是使用start()方法,而不是直接调用run()方法。

直接调用run方法,相当于主线程main直接调用run这个方法,虽然执行的代码逻辑是一样的,但是主线程里面的代码是顺序执行的,不是另外开了一个子线程并行处理。

start()源码:start()方法内部调用的是start0()方法,是JVM调用,底层是C/C++实现。真正实现多线程效果的是start0()方法,而不是run()。start()方法是将该线程加入一个group集合中,只是将线程设置为可以运行的状态,有JVM来决定何时启动该线程。

 group.add(this);//加入待启动集合

        boolean started = false;
        try {
            start0();//native方法,由JVM来进行调用
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }

2.2 实现Runnable接口创建线程

该方法实现创建线程类使用到了静态代理这种设计模式,这里描述一下本人对该模式的理解。其中实现该模式需要有两个对象和1个接口的参与。其中为:代理类即本代码的Thread类,被代理类即Dog类以及我们的Runnable接口。我们的目标是让被代理类(Dog)作为主体来创建一个线程,而创建线程就需要调用start()方法。但是Dog类并没有start()方法。此时静态代理模式的几个步骤为:

  1. 让被代理的类和代理类都实现Runnable接口。
  2. 代理类的构造器需要将代理类作为参数传入。
  3. 代理类的run方法的方法体就是调用代理类的run方法,即代理执行。
  4. 通过调用代理类的start方法来间接让代理类作为主体创建一个新的线程。

这个是我所理解的通过静态代理的设计模式来实现创建线程的方法和步骤,如果有错误的地方,还请海涵。

public class TreadTest2 {
    public static void main(String[] args) {
//        Dog dog = new Dog();
//        //无法直接使用dog.start();启动线程
//        Thread thread = new Thread(dog);
//        thread.start();
    }
}

class Dog implements Runnable{//通过Runnable接口实现线程类
    int count = 0;
    
    public void run() {
        while (true){
            System.out.println("小狗汪汪叫... hi "
                    + (++count) + Thread.currentThread().getName());
            //休眠1秒
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            if(count == 10){
                break;//退出线程
            }
        }
    }
}

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

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

相关文章

osg earth中加载标签并设置文字 以及使用注意事项

osgearth中加载标签并设置文字 //头文件 #include <osgEarthAnnotation/PlaceNode> #include <osgEarthSymbology/Style> #include <osgEarth/MapNode> osgEarth::GeoPoint position(m_mapnode->getMapSRS(), lon, lat, 0, osgEarth::AltitudeMode::ALTM…

数据驱动商业合作:企业联系方式查询API在市场中的角色与作用

摘要 在当今数字化商业环境中&#xff0c;企业间的商务合作和合作伙伴关系构建变得更加重要。为了有效推进商业拓展和建立持久合作&#xff0c;企业需要快速、准确地获取潜在合作伙伴的联系方式。本文将深入探讨企业联系方式查询 API 在市场中的角色与作用&#xff0c;以及它如…

JetBrains全家桶:如何自定义实现类TODO注释?

文章目录 效果图具体方法参考文献 效果图 TODO注释大家应该都用过&#xff0c;在注释开头打上TODO的话&#xff0c;软件下方的TODO选项卡里就可以自动筛选出你打了TODO的注释&#xff0c;你可以点击里面对应的注释来实现快速跳转。 jetbrains全家桶&#xff08;如Pycharm、Int…

LKT(LCS)系列IIC接口加密芯片

调试常见问题&#xff08;一&#xff09; 1.加密芯片的数据交互协议是什么格式&#xff1f; 发送时&#xff1a;地址两字节数据长度&#xff08;后续数据的长度&#xff09;后续数据内容。Eg.50 0005 0084000008。接收时&#xff1a;地址两字节数据长度&#xff08;后续数据的…

万字长文详解Webpack5高级优化

本文从 4 个角度对 webpack 和代码进行了优化&#xff1a; 1.提升开发体验 使用 Source Map 让开发或上线时代码报错能有更加准确的错误提示。 2.提升打包构建速度 使用 HotModuleReplacement 让开发时只重新编译打包更新变化了的代码&#xff0c;不变的代码使用缓存&#xff…

Github Flow工作流简单介绍(以部署为中心的开发模式)

前言 这篇文章主要介绍Github Flow的理念&#xff0c;以下内容来源于《Github入门与实践》。 Github Flow是以部署为中心的开发模式&#xff0c;通过简单的规则&#xff0c;持续高速且安全地进行部署。而Gitflow则是以发布为中心的分支管理模型&#xff0c;它提供了一种更灵活…

【Docker】Docker容器编排

目录 一、Docker Compose1.2Docker Compose 环境安装1.3 YAML 文件格式及编写注意事项2.3 Docker Compose配置常用字段2.4 Docker Compose 常用命令 二、Docker Compose实验2.1编写Nginx的Dockerfile脚本2.2编写MySQL&#xff0c;Dockerfile脚本2.3编写PHP&#xff0c;Dockerfi…

QT样式表qss中的长度单位px/pt/%/em/ex/mm/in等

以下是从CSS里抄来的。QSS只能支持其中一部分。 1、px&#xff1a;像素(Pixel),相对于设备的长度单位&#xff0c;像素是相对于显示器屏幕分辨率而言的。譬如&#xff0c;WONDOWS的用户所使用的分辨率一般是96像素/英寸。而MAC的用户所使用的分辨率一般是72像素/英寸。 像素&a…

在培训班里学IT技术是否有用?和大家分享相关IT培训班里五大常见宣传手法、相关优势与实际效果

目录 Introduction 引言IT培训班常见宣传手法培训班的优势如何评判IT培训班的效果与质量除IT培训班之外的学习渠道总结其它资料下载 Introduction 引言 随着信息技术的飞速发展&#xff0c;学习IT技术成为许多人追求职业发展和个人兴趣的重要途径。从软件开发、数据科学到人工…

OpenAI Code Interpreter 的开源实现:GPT Code UI

本篇文章聊聊 OpenAI Code Interpreter 的一众开源实现方案中&#xff0c;获得较多支持者&#xff0c;但暂时还比较早期的项目&#xff1a;GPT Code UI。 写在前面 这篇文章本该更早的时候发布&#xff0c;但是 LLaMA2 发布后实在心痒难忍&#xff0c;于是就拖了一阵。结合 L…

插件使用权限管理软件(一)框架选择和Furion框架搭建

项目背景 软件主要服务于传统设计院&#xff0c;用于管理和监控设计院内部插件的使用权限和使用情况。可根据使用的频率来对插件使用情况的分析。后续可以加上错误报告等提测报告&#xff0c;使整个监控插件使用情况更加流程化。由于博主主要做CAD和Revit的二次开发工作&#x…

【力扣每日一题】2023.7.25 将数组和减半的最少操作次数

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码运行结果&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 题目给我们一个数组&#xff0c;我们每次可以将任意一个元素减半&#xff0c;问我们操作几次之后才可以将整个数组的和减半&…

实例025 带分隔栏的窗体

实例说明 在软件开发中&#xff0c;经常需要将界面分成几个部分&#xff0c;而且这几个部分又可以自由调整大小。运行本例&#xff0c;实例效果如图1.25所示。 技术要点 在.NET 2.0框架中可以非常轻松的实现这一功能&#xff0c;只要在窗体中加入SplitContainer控件即可。Sp…

2023年深圳杯数学建模A题影响城市居民身体健康的因素分析

2023年深圳杯数学建模 A题 影响城市居民身体健康的因素分析 原题再现&#xff1a; 以心脑血管疾病、糖尿病、恶性肿瘤以及慢性阻塞性肺病为代表的慢性非传染性疾病&#xff08;以下简称慢性病&#xff09;已经成为影响我国居民身体健康的重要问题。随着人们生活方式的改变&am…

Cesium态势标绘专题-自由多边形(标绘)

标绘专题介绍:态势标绘专题介绍_总要学点什么的博客-CSDN博客 入口文件:Cesium态势标绘专题-入口_总要学点什么的博客-CSDN博客 辅助文件:Cesium态势标绘专题-辅助文件_总要学点什么的博客-CSDN博客 本专题没有废话,只有代码,代码中涉及到的引入文件方法,从上面三个链…

红外雨量计(光学雨量传感器)调试

红外雨量计&#xff08;光学雨量传感器&#xff09;调试 红外雨量计是一种用来测量雨量的传感器&#xff0c;它通过红外线的反射来检测雨滴的落下。为了调试红外雨量计&#xff0c;你需要参考以下步骤&#xff1a; 1. 确认传感器的电源接线正确。检查传感器的接线是否正确&…

软工导论知识框架(二)结构化的需求分析

本章节涉及很多重要图表的制作&#xff0c;如ER图、数据流图、状态转换图、数据字典的书写等&#xff0c;对初学者来说比较生僻&#xff0c;本贴只介绍基础的轮廓&#xff0c;后面会有单独的帖子详解各图表如何绘制。 一.结构化的软件开发方法&#xff1a;结构化的分析、设计、…

GBASE南大通用出席CCF第38届中国计算机应用大会

在数据要素市场化分论坛上&#xff0c;GBASE南大通用高级副总裁赵伟发表“以自主可控的国产基础软件新兴技术保障数据要素安全高效流通”的主题演讲&#xff0c;向参会嘉宾分享基于GBASE数据库的自主可控国产软件&#xff0c;保障数据要素安全流通、高效流转的创新实践。 赵伟讲…

基于STM32设计的智能奶瓶

一、项目背景 随着我国计划生育政策的放开,婴幼儿数量持续上涨,国民收入逐年提高,家庭在婴幼儿产品方面的消费日益扩大。奶瓶是母婴市场的刚需。目前婴儿哺育的问题引起新爸新妈的高度重视。一方面,人们使用的传统奶瓶已经不能很好地满足现代人对于智能化生活的需求。另一…

C语言非常道 6.4习题解答

关于 #include “stdarg.h” 相关知识小结&#xff1a; 函数&#xff1a;tppedef va_list char * ; va_list al; va_start(al, fmt) 使 al 指向变参函数中最后一个已知参数&#xff08;从右往左数的第一个已知参数&#xff09; va_arg(两个参数&#xff09;&#xff0c;第一个…