Java中创建线程的五种方式

news2025/1/9 1:22:52

目录:

前言

1.进程与线程的区别?

2.进程是操作系统进行资源分配的基本单位,而操作系统是以线程为单位进行调度的。

3. Java操作多线程,依赖最核心的类Thread。

4.关于start和run的区别?

5.使用JDK自带的工具jconsole来查看当前java进程中的所有线程。

Java中创建线程的五种写法

1.继承Thread,重写run

2.实现Runnable接口

3.使用匿名内部类,继承Thread

4.使用匿名内部类,实现Runable

5.使用Lambda表达式



前言

进程与线程的区别?

(参考之前写的一篇博客:多进程编程 VS 多线程编程_crazy_xieyi的博客-CSDN博客_多进程编程和多线程编程创建线程/销毁线程比创建进程/销毁进程更加高效和轻量。所以,一般情况下,会使用多线程来进行开发。但是,多进程也有它自己独特的优势,进程的“独立性”更好。进程要比线程来的更加稳定一点。虽然进程没有线程那么高效,但是它的独立性带来的稳定是非常关键的,在某些场景下必须使用多进程编程。https://blog.csdn.net/crazy_xieyi/article/details/127427551?spm=1001.2014.3001.5501%EF%BC%89

因为CPU现在进入了多核心的时代,要想进一步提高程序的执行速度,就需要充分的利用CPU的多核资源。引入进程这个概念,最主要的目的就是为了解决并发编程这样的问题。其实多进程编程已经可以解决并发编程的问题了,但是进程太重了,在资源分配和回收上的消耗资源多且速度比较慢,创建销毁调度进程的开销比较大。这个时候就引入了线程的概念,线程也可以叫做“轻量级进程”,在解决并发编程的前提下,让创建销毁调度的速度更快一些。因为线程是把资源的申请和释放的操作给省略了,所以更轻更快。

进程和线程的关系:进程包含线程,一个进程可以包含一个线程,也可以包含多个线程。只有第一个线程启动的时候,开销与创建进程相当,但是后续线程就省事了。同一个进程里面的多个线程之间是共用了进程的同一份资源,比如内存(线程1 new的对象在线程234中都可以直接使用)和文件描述符表(线程1打开的文件在线程234中都可以直接使用)。

进程是操作系统进行资源分配的基本单位,而操作系统是以线程为单位进行调度的。

关于进程的调度,是每个进程里面只有一个线程这样的情况,如果每个进程里面有多个线程了,每个线程是独立在CPU上调度的。其中一个线程也是通过一个PCB来描述的,一个进程里面可能是对应一个PCB,也可能是对应多个PCB。PCB的状态、上下文、优先级和记账信息都是每个线程有自己的,各自记录各自的。但是同一个进程里面的PCB之间的pid是一样的,内存指针和文件描述符表也是一样的(在Linux中不区分TCP和PCB,都用一个表示)。

关于多线程问题,当线程足够多,而系统资源有限的情况下,可能会引发线程安全问题;还有就是其中一个线程出现异常,那么很可能把整个进程都带走,其他线程也就跟着凉凉了(我们看到谷歌浏览器就是每个页面都是做的一个进程,所以谷歌浏览器占用的系统资源挺多的)。

在Java中进行多线程编程,要依赖于操作系统提供的API。关于Java能够跨平台,其实是靠无数个不同版本的JVM支持的,比如windows系统实现了一个windows版本的JVM,Linux系统实现了一个Linux版本的JVM,Mac系统实现了Mac版本的JVM,这些不同的JVM内部封装了不同系统的API。

 Java操作多线程,依赖最核心的类Thread。

ca71cf69be8f407ba5d22f717106d253.png

关于t1.start;是线程中的特殊方法,启动一个线程。Start的工作就是创建一个新的线程,新的线程负责执行run()方法。Start就是调用了操作系统的API,通过操作系统的内核创建新线程的PCB,并且把要执行的指令交给到这个PCB,当PCB被调度到CPU上执行的时候,也就执行到了线程run方法中的代码了。

关于操作系统调度线程,是“抢占式执行”,具体哪一个线程先上哪一个线程后上是不确定的,取决于操作系统调度器具体的实现策略。

关于start和run的区别?

Start是真正在系统上创建一个线程,线程是一个独立的执行流。而run只是描述了线程要干的活是啥。如果直接在main方法中调用run,那么此时是没有创建新的线程的,全是main所在线程一个人干活。

我们可以使用JDK自带的工具jconsole来查看当前java进程中的所有线程。

240036179d224ee19bb56cfa3427773a.png

35726a06b2a5426c87b92cea148361cb.png 

40b52e811dc841f5874ccdfd83db9e42.png 

Java中创建线程的五种写法

1.继承Thread,重写run

 f56ccce55f2a4ad9b737565f6ab7887a.png

package threadtest;
class MyThread1 extends Thread{
    @Override
    public void run() {
        while (true) {
            System.out.println("hello thread");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public class ThreadDemo2 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new MyThread1();
        t1.start();//注意:这里start并没有调用run方法,而是创建了一个新的线程,由新的线程来执行run方法。
        while (true) {
            System.out.println("hello main方法");
            Thread.sleep(1000);
        }
    }
}

 2.实现Runnable接口

 5f1ef5ac0c8d42adb539a725420c4e16.png

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

    @Override
    public void run() {
        System.out.println("hello thread");
    }
}
public class ThreadDemo3 {
    public static void main(String[] args) {
        Runnable runnable = new MyRunnable();
        Thread t1 = new Thread(runnable);
        t1.start();
    }
}

 这样的写法可以解耦合,目的就是让线程和线程需要干的活分开。

3.使用匿名内部类,继承Thread

28e43be9bfb94550a1e3107b5d29a9cb.png

public class ThreadDemo4 {
    public static void main(String[] args) {
        Thread t = new Thread(){
            @Override
            public void run() {
                System.out.println("hello thread");
            }
        };
        t.start();
    }
}

 new Thread(){}创建了一个Thread子类,子类没有名字所以叫做匿名,创建了子类的实例,并且让t引用指向该实例。

4.使用匿名内部类,实现Runable

c3a4b2baca94457882cec5b74b33ec18.png

public class ThreadDemo5 {
    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello runnable");
            }
        });
        t.start();
    }
}

 这个写法与第二个本质是相同的,只不过是把实现Runnable任务了交给匿名内部类。此处是创建了一个类,实现了Runnable,同时创建了类的实例,并且传给了Thread的构造方法。

5.使用Lambda表达式

33489ccdef3b483fb7c70e7f1b260f2a.png

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

 把任务用Lambda来描述,直接把Lambda传给Thread方法。

 

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

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

相关文章

ArcGIS基础实验操作100例--实验7分割多部分要素

本实验专栏来自于汤国安教授《地理信息系统基础实验操作100例》一书 实验平台:ArcGIS 10.6 实验数据:请访问实验1(传送门) 基础编辑篇--实验7 分割多部分要素 目录 一、实验背景 二、实验数据 (1)查看多…

第05讲:Redis主从复制

一、关于主从复制 1.1、什么是主从复制 主机数据更新后根据配置和策略, 自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主 1.2、主从复制的作用 读写分离,性能扩展容灾快速恢复 二、一主多从的实验 2.1、原…

GitHub+HEXO博客设置主题

文章目录安装主题修改站点配置文件修改主题配置文件部署到github补充由于之前使用HexoGitHub搭建了个人博客用的是最原始的主题,丑的一批QAQ 用一下Github上面Star最高Next主题look look! 上节博客:HexoGitHub搭建个人博客 主题选取网站&a…

CnOpenData中国工业企业基本信息扩展数据

一、数据简介 拉动中国经济的三个产业中,工业企业占有特殊的地位,是推动国内经济发展的重要产业。工业是最主要的物质生产部门,为居民生活、各行业的经济活动提供物质产品,这一重要作用是其他任何产业部门都无法替代的。工业企业为…

拆串后结构化,其中按行对齐

【问题】 I have a bit weired scenario where i need to fetch data i have following three products product1 product2 product3and each product has different ids(e.g. p1345,p3453,p2345) and then each froduct have different options which are having different…

算法题刷累了就来试试游戏吧----2048小游戏----C语言实现

目录 1. 代码前的准备 2. 游戏思路及代码分析 2.1 game.h 代码分析 2.2 test.cpp代码分析 3. 完整代码 3.1 game.h 3.2 game.cpp 3.3 test.cpp 嘿嘿嘿,写游戏还是挺高兴的撒,如果你还不知道2048这个小游戏的规则,那么快去试试吧。不然…

项目管理误区:项目不确定性≠项目风险

项目失败的原因千千万万,罪魁祸首肯定跟“它”脱不了关系! 前段时间,偶然看到一个求助贴引发了各路网友(项目经理)的热议。求助人的问题是:“如何管理项目中的不确定性?” 下面的回复已然偏离答…

Linux系统运行时参数命令--文件IO性能监控

目录 4 文件IO性能监控 4.1 I/O 的两种方式(缓存 I/O 和直接 I/O) 1 缓存 I/O 2 直接 I/O 4.2 监控磁盘I/O的命令 1 iostat IO状态 2 swapon查看分区使用情况 3 df硬盘使用情况 4 du目录文件大小 4.3 文件IO写入频繁案例分析 C/CLinux服务器开发/后台架构师【零声教育…

IU8689+IU5706 单声道100W/立体声60W同步升压+功放IC大功率拉杆音箱应用组合方案

引言 目前中大功率拉杆音箱主要采用12V铅酸电池为供电电源,在电源直供的时候,一般的功放芯片输出功率在20W左右(喇叭为4欧、THD10%)。超过50W的功率现阶段市场上主要采用升压芯片TPA3116的组合解决方案。 随着竞争的加剧&#x…

如何进行数据可视化图表设计?

如何进行数据可视化图表设计? 对数据人来说,数据可视化是分析理解数据,并最终呈现数据的必修课。本文从以下几个点来说明,如何进行数据可视化图表设计。1、数据背后的故事2、充分理解数据3、多种图表类型设计指南 1数据背后的故…

安克创新能否锚定全球家用储能市场 隆起新的增长极?

提到能源储存,似乎应该是涉及一个国家或者地区的宏大概念。但事实上,储能正在走向家用领域。 近年来,全球能源价格持续高涨,但家用储能的成本却随着锂电等新能源技术的发展在逐渐下降,经济性开始凸显。家用储能在海外…

用HTML制作独一无二的2022回忆旋转相册

目录 前言 效果展示 流程 前言 元旦即将来临,展望2022,我们可以制作一个自己的2022回忆的旋转相册,通过下面的方法来学习吧 效果展示 制作好后,十张相册会在下面旋转,可以改为自己想要放的照片和音乐,制…

史上最简单的推箱子(AS3.0版)

我最熟悉的语言是 AS3.0,现在主要用C,还想学学Python,因此,最近一段时间先用AS3.0实现了最简版的推箱子、贪吃蛇和俄罗斯方块,然后换Python实现,算是熟悉了一下Python的基本用法,最后用C实现&a…

微信小程序 Spdier - OfferShow 反编译逆向(一)

微信小程序 Spdier - OfferShow 反编译逆向(一) 文章目录微信小程序 Spdier - OfferShow 反编译逆向(一)前言一、任务说明1.尝试反编译分析出js_code参数的生成方式,用来获取token2.将小程序搜索出来的数据保存至本地e…

【Java开发】Spring Cloud 01 :微服务前提精要

算是新开了一个 Spring Cloud 的坑,本文来源于姚半仙的《Spring Cloud 微服务项目实战》课程,大部分文字内容基于该课程,我的工作可能就是梳理归纳和拓展,希望尽快搞懂相对来说较为简单的 Spring Cloud Alibaba 微服务框架&#x…

决策树及分类原理与划分依据:信息熵、信息增益、信息增益率、基尼值和基尼指数

一、决策树及分类原理 决策树:是一种树形结构,其中每个内部节点表示一个属性上的判断,每个分支代表一个判断结果的输出,最后每个叶节点代表一种分类结果,本质是一颗由多个判断节点组成的树 熵(Entropy) :…

PostgreSQL数据库查询执行——SeqScan节点执行

SeqScan节点代码处于src/backend/executor/nodeSeqscan.c文件中,包含了4个重要函数:ExecInitSeqScan、ExecSeqScan、ExecReScanSeqScan和 ExecEndSeqScan。 ExecInitSeqScan src/backend/executor/nodeSeqscan.c文件中的ExecInitSeqScan函数&#xff0c…

数智化转型给企业带来了什么?

数智化转型的核心价值之一在于对企业创智型活动的赋能,从用户需求趋势预测到创意快速验证,数智化应用具有巨大的价值前景。 因此,尽管目前数智化研发还存在着一定程度的复杂性高、不确定性大等问题,但因数智化研发所具有极大的潜…

C# 网络信息获取

一 网络信息浏览 1 HTTP协议 2 客户端与服务器 3 Request与Response 4 Stream 5 Get与Post 二 一些查看工具 1 Fiddler2 http://www.fidddler2.com 2 其他工具 如NetworkMoniter、Visula Sniffer、httpwatch、WireShark 3 Chrom/FireFox等浏览器F12 ① Chrome 中按F…

泛微齐业成,一文告诉你如何实现全程数字化的预算管理

新一代全程数字化费控管理软件-齐业成预算管理,实现从预算建模、预算编制、预算审批、预算管控、预算变更、预算分析、预算考评的全程数字化管理。 随着数字经济和数字社会的高速发展,预算管理已成为组织内部最重要的经营管理活动之一,其过程…