如何使用多线程

news2024/9/23 1:38:06

一个进程正在运行时,至少会有一个线程在运行。

package ChapterOne;

public class Test {
    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getName());
         //currentThread方法返回正在被执行的线程的信息
        //getName返回正在被执行线程的名字
    }
}

执行结果:

这里输出的main其实是一个名字为mian的线程在执行main()方法中的代码,也就是说,当前线程的名字mian与mian()方法无关。该线程由JVM创建。

package ChapterOne.test1;

public class A {
    public static void main(String[] args) {
        B b = new B();
        b.bMethod();
    }
}
package ChapterOne.test1;

public class B {

    public void bMethod() {
        System.out.println("B bMethod "+Thread.currentThread().getName());
    }
}

运行结果:

这里B类中的bMethod方法打印出当前执行线程的名称依旧是main,进一步说明当前线程名称为main与jmain方法无关。

Java中实现多线程编程的方式主要有两种:一种是继承Thread类,另一种是实现Runnable接口。

继承Thread类

Thread的声明:
public
class Thread implements Runnable 

由此可见,Thread类实现了Runnable接口,也就是说,它们之间存在多态的关系。

package ChapterOne.myThread;

public class MyThread extends Thread{
    Runnable r1 = new Thread();
    Runnable r2 = new MyThread();
    Thread r3 = new MyThread();
}

使用Thread创建新线程时,最大的局限就是由于Java语言的单根继承特点,所以继承Thread类后就不能再继承其他类了,如果必须要继承其他类,就可以使用实现Runnable接口的方式来创建新线程。这两种方式创建线程的功能是一样的,本质上没有什么区别。

start()方法和run()方法
package ChapterOne.myThread;

public class MyThread extends Thread{
    @Override
   public void run(){
        super.run();
        System.out.println("MyThread");
   }
}
package ChapterOne.test;

import ChapterOne.myThread.MyThread;

public class Run {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();
        System.out.println("运行结束。");
    }
}

运行结果:

这里使用start()方法启动一个线程,线程启动后调用线程对象中的run()方法,而run()方法中的代码就是说线程对象将要执行的内容,它是线程执行任务的入口。

run()方法:这个线程要做什么,是线程执行任务的入口。

start()方法:启动线程。

从上述代码中的执行情况可以看出, System.out.println("运行结束。");耗时较小,而 myThread.start();耗时较大,原因在于:

start()方法内部执行了多个步骤

  • 首先,要通过JVM告诉操作系统创建Thread。
  • 然后,操作系统开品内存并通过一些步骤创建Thread线程对象。
  • 之后,操作系统对Thread对象进行调度,确定其执行时机。
  • 最后,Thread在操作系统中被成功调用。

而main()线程执行start()方法时,并不需要等待其执行完毕再去执行下一行代码。

在这种情况下,也有可能先输出MyThread再输出运行结束,这也就是线程执行的顺序具有随机性。

实现Runnable接口

上面我们谈到,如果想创建的线程已经有了一个父类,就不能继续继承Thread类了。这个时候我们采用实现Runnable的方式来创建线程。

Thread的构造函数

在Thread的构造函数中,有五个构造方法可以传入Runnable接口,这说明构造方法支持传入一个Runnable接口的对象。

package ChapterOne.myRunnable;

public class Run {
    public static void main(String[] args) {
        Runnable runnable = new myRunnable();
        Thread thread = new Thread(runnable);
        thread.start();
        System.out.println("运行结束");
    }
}
package ChapterOne.myRunnable;

public class myRunnable implements Runnable{
    @Override
    public void run() {
        System.out.println("运行中");
    }
}

运行结果:

执行结果依旧是异步执行。

使用Runnable接口的优点

Java是单继承,因此在要创建的线程已经继承其他父类时,不能再使用Thread类来创建线程,此时只能通过实现Runnable接口来创建线程。

package ChapterOne.myRunnable;

public class AServer {
    public void a_save_method(){
        System.out.println("a中的保存数据方法被执行");
    }
}
package ChapterOne.myRunnable;

public class BServer extends Thread,AServer{
    public void b_save_method() {
        System.out.println("a中的保存数据方法被执行");
    }
}

存在问题:

进行更改

package ChapterOne.myRunnable;

public class BServer extends AServer implements Runnable{
    public void b_save_method() {
        System.out.println("a中的保存数据方法被执行");
    }

    @Override
    public void run() {
        b_save_method();
    }
}

由于Thread也实现了Runnable接口。

所以,构造函数Thread(Runnable target)中不仅可以传入Runnable接口的对象,还可以传入一个Thread对象。

package ChapterOne.myRunnable;

import ChapterOne.myThread.MyThread;

public class Test {
    public static void main(String[] args) {
        MyThread thread = new MyThread();
        Thread t = new Thread(thread);
        t.start();
    }
}

MyThread是Thread的子类,而Thread是Runnable的实现类,所以MyThread也相当于是Runnable的实现类。

使用Runnable接口方式实现多线程可以把”线程“和”任务“分离。Thread代表线程,而Runnable代表可运行的任务。Runnable中包含Thread线程要执行的代码,也就是说这样可以实现多个Thread共用一个Runnable。

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

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

相关文章

【Docker】Docker实战

文章目录 搭建nginx服务搭建私有库Busybox阿里云上创建私有库 搭建nginx服务 首先拉取nginx的镜像。 docker pull nginx:1.24.0以后台的方式运行nginx,并且创建一个shell进行交互。 docker run --name nginx1 --rm -it -p 8080:80 nginx:1.24.0 bash#在交互的bas…

Kubernetes_核心组件_KubeProxy_Service找到Pod与DNS解析Service/Pod

文章目录 前言一、Service找到Pod(Iptables)二、Service找到Pod(IPVS)2.1 IPVS模式原理2.2 IPVS模式实践修改为 IPVS 模式 之前修改为 IPVS 模式之中修改为 IPVS 模式之后 三、Service和Pod的DNS域名3.1 Service DNS域名3.2 Service与Deployment/StatefulSet配合Deployment普通…

无源光网络(PON)介绍及其应用

文章目录 1、无源光网络(PON)介绍ONU(Optical Network Unit),光网络单元OLT(Optical line terminal),光线路终端 2、FTTH、FTTB、FTTR组网介绍FTTR组网规划 3、局端接入设备产品介绍…

Elasticsearch 基本使用(五)查询条件匹配方式(query query_string)

查询条件匹配方式 概述querytermtermsrangematch_allmatchmatch 匹配精度问题 match_phrasematch_pharse_prefixmatch_bool_prefixmulti_match query_string简单查询一个字段在多个字段上应用同一个条件 (类似multi_match)在所有字段上应用同一个条件 &a…

mysql 大数据量从“.log“文件插入方法

要被插入的数据文件以及内容 表结构 插入成功,插入时如果有主键唯一索引,则按照唯一索引的大小顺序插入,速度会快很多

基于Spring Boot的智能学生考勤系统设计与实现(Java+spring boot+MySQL+微信小程序+

获取源码或者论文请私信博主 演示视频: 基于Spring Boot的智能学生考勤系统设计与实现(Javaspring bootMySQL微信小程序人脸识别) 使用技术: 前端:html css javascript jQuery ajax thymeleaf 后端:Java…

SpringBoot 如何使用 TestEntityManager 进行 JPA 集成测试, 如何使用

Spring Boot 是一个非常流行的 Java Web 开发框架,它简化了开发过程,提高了开发效率。在开发过程中,我们通常需要使用 JPA 操作数据库,为了保证代码的质量和正确性,我们需要进行集成测试。TestEntityManager 是 Spring…

bat批处理脚本控制台输出中文乱码问题

背景 最近在搞springcloud框架,涉及各种微服务。比如服务注册与发现、网关、鉴权、文件服务、日志服务、搜索服务、用户中心等等。如果要打包发布应用,就得一个个去打包,一个个去拷贝jar包,很繁琐。所以就想着写个bat脚本&#x…

【Zookeeper】使用Curator操作Zookeeper

简介 Curator 是 Apache ZooKeeper 的Java客户端库。 Zookeeper现有常见的Java API如&#xff1a;原生JavaAPI、Curator、ZkClient等。 添加依赖 <dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</artifactId&…

gitlab:(二)gitlab添加win10 台式机的ssh key

当前gitlab版本为12系列&#xff1a; 点击settings 找到ssh keys &#xff0c;再找到“ generate one or use an existing key.” 点击 generate one 参考如下的教程&#xff1a; window cmd 命令行示例 添加 ssh keys 添加的效果

路由基本使用

编程式导航 默认路由 模糊匹配模式 精确匹配

【C语言】指针进化 !!!

前言 &#x1f388;大家好&#xff0c;我是何小侠&#x1f388; &#x1f343;大家可以叫我小何或者小侠&#x1f343; &#x1f490;希望能通过写博客加深自己对于学习内容的理解&#x1f490; &#x1f338;也能帮助更多人理解和学习&#x1f338; 兰生幽谷&#xff0c;不为…

Redis 五种基本数据结构及基本使用

一、数据结构 二、使用 2.1 String 的使用 Redis String 一个键对应一个值&#xff0c;并且是二进制安全的&#xff0c;值可以是图片或者序列化后的对象。 一个键最大能存储 512 MB。 2.1.1 set 命令的使用 set key value127.0.0.1:6379> set name yunhu OK 127.0.0.1:…

【Docker】docker基础使用

文章目录 docker概念什么是dockerdocker引擎迭代docker与虚拟机docker版本发展 docker基础docker架构docker Registry(镜像仓库)镜像仓库使用流程实际研发镜像仓库使用不同镜像仓库的拉取 docker常用命令镜像仓库命令docker logindocker pulldocker pushdocker searchdocker lo…

Github的加速访问(解决github进不去)

1.下载Steam Steam 现更名为 Watt Toolkit 并在 Microsoft Store 中已可用 2.打开Steam 3.勾选github 一键加速

java试题1

1、哪些问题是HTTPS无法解决的&#xff1f; Http是基于TCP协议的&#xff0c;在网络层的传输耗时比较长&#xff0c;https没有解决这个问题&#xff1b;http头是不能压缩的&#xff0c;每次要传递很大的数据包&#xff0c;每个连接也只能支持一个请求。同时https应用了很多加密…

Docker - 基本概念、与虚拟机的区别、架构、镜像操作、容器操作、数据卷挂载

目录 一、对 Docker 的理解 1、Docker 基本概念 2、Docker 与 虚拟机的区别 3、何为镜像和容器&#xff1f; 4、Docker 主要架构 二、Docker 基本操作 1、Docker 镜像操作 2、案例&#xff08;镜像&#xff09;&#xff1a;去 DockerHub 搜索并拉取一个 Nginx 镜像&am…

第一百天学习记录:线性代数:行列式(宋浩板书)

n阶行列式 注&#xff1a;二阶行列式和三阶行列式以及排列和逆序数见高等数学自学向量篇中间穿插的线性代数知识点补充。 行列式的性质 性质7&#xff08;☆☆☆&#xff09; 行列式按行展开 拉普拉斯 行列式相乘 行列式的计算 Cramer法则 题外话&#…

【unity实战】制作类元气骑士、挺进地牢——俯视角射击游戏多种射击效果(一)(附源码)

文章目录 本期目标前言欣赏开始1. 角色移动和场景搭建2. 绑定枪械2.1 首先将各种枪械的素材添加给人物作为子物体2.2 给枪械也分别添加两个子物体用作标记枪口和弹仓位置 3. 枪械动画4. 切换枪械5. 发射功能5.1 手枪(1) 枪械随着鼠标旋转(2) 射击时间间隔(3) 创建好子弹、弹壳和…

xilinx zc706 10/100/100M以太网完整性测试说明

一&#xff1a;概述 最近接触FPGA比较多&#xff0c;本次是一款zc706芯片的FPGA&#xff0c;开发版是长这样的&#xff0c;基本上开发也是安装开发版的模块组合进行开发。 开发版上以太网芯片使用的是Marvell 881116R。 本次只是验证下控制以太网进行模式测试的说明&#xf…