当前位置: 首页 > news >正文

线程类以及创建多线程的第一种方式---继承Thread类

先来看一个例子理解主线程和单线程:

/*
主线程:执行主(main)方法的线程
单线程程序:Java程序中只有一个线程
程序从main方法开始,从上到下依次执行
 */
public class Demo11MainThread {
    public static void main(String[] args) {
        Person p1 = new Person("易烊千玺",18);
        Person p2 = new Person("王俊凯",19);
        p1.run();
        p2.run();
    }
}

过程:

首先JVM执行应用程序,main方法,从方法区进入到栈中,JVM会找操作系统开辟一条main方法通向cpu的执行路径(线程),然后cpu就可以通过这个路径来执行main方法,这个路径名字就是主线程。

单线程弊端:由于是从上到下依次执行,中间有环节出现异常的时候,后面的任务也会终止,因此引入多线程的使用。

 

创建线程类

Java使用java.lang.Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例,每个线程的作用是完成一定的任务,实际上就是执行一段程序即一段顺利执行的代码。Java使用线程执行体来代表这段程序流。

Java创建多线程有两种方式:

第一种:Java中通过继承Thread类来创建并启动多线程的步骤如下:

1.定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务,因此把run()方法称为线程执行体。

2.创建Thread子类的实例,即创建了线程对象

3.调用线程对象的start()方法来启动该线程

 

 void

start()
          使该线程开始执行;Java 虚拟机调用该线程的 run 方法。

结果是两个线程并发地运行;当前线程(main线程)和另一个线程(创建的新线程,执行其 run 方法):

多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。

Java程序属于抢占式调度,哪个线程的优先级高,就先执行,优先级相同,就随机选择一个执行。

/*
线程类的子类,重写run()方法
 */
public class MyThread extends Thread{
    // 1.定义Thread类的子类,并重写该类的run()方法
    @Override
    public void run() {
        // super.run();
        for (int i = 0; i < 20; i++) {
            System.out.println("run" + i);
        }
    }
}
public class Demo11Thread {
    public static void main(String[] args) { // 并发运行的第一个线程
        // 2.创建Thread类的子类对象
        MyThread mt = new MyThread();
        // 调用Thread类中的方法start方法,开启新的线程,执行run()方法
        mt.start(); // 开启新的(第二个线程)

        for (int i = 0; i < 20; i++) { // 主线程的代码块
            System.out.println("main" + i);
        }
    }
}

执行结果:

从结果可以看出来,Java采用抢占式调度,优先级相同,随机选择执行。

 

多线程运行原理

以上述代码举例,解释多线程程序的执行流程:

多线程内存图解

main方法压栈执行,new的对象在堆内存中分配一块空间,并将内存地址值赋值给相应变量mt,执行mt.run(),方法压栈运行(此时为单线程,是对象调用方法,而不是创建新的线程),运行到mt.start()时,并不是方法压栈执行,而是开辟一个新的栈空间。

 

 

相关文章:

  • Thread类的构造方法及常用方法
  • 创建多线程的第二种方式--实现Runable接口
  • Thread和Runnable的区别和匿名内部类方式实现线程的创建
  • 线程安全
  • 数据结构基本概念和术语
  • 线程状态
  • Object类中wait带参方法和notifyAll方法
  • File类
  • 递归(斐波那契数列、类加、累乘、打印多级目录)
  • FileFilter过滤器
  • LeetCode两数之和
  • 稀疏数组
  • 队列
  • 单链表LinkedList的增删改查
  • 双向链表和环形链表(单向和双向)约瑟夫环实例
  • go append函数以及写入
  • iOS筛选菜单、分段选择器、导航栏、悬浮窗、转场动画、启动视频等源码
  • Java知识点总结(JavaIO-打印流)
  • maya建模与骨骼动画快速实现人工鱼
  • nginx 负载服务器优化
  • oschina
  • Redis的resp协议
  • 飞驰在Mesos的涡轮引擎上
  • 聊聊redis的数据结构的应用
  • 前端性能优化--懒加载和预加载
  • 十年未变!安全,谁之责?(下)
  • 世界编程语言排行榜2008年06月(ActionScript 挺进20强)
  • 说说动画卡顿的解决方案
  • 微信公众号开发小记——5.python微信红包
  • 微信开源mars源码分析1—上层samples分析
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • 我的面试准备过程--容器(更新中)
  • 智能网联汽车信息安全
  • #1015 : KMP算法
  • #宝哥教你#查看jquery绑定的事件函数
  • $jQuery 重写Alert样式方法
  • (9)YOLO-Pose:使用对象关键点相似性损失增强多人姿态估计的增强版YOLO
  • (C++17) std算法之执行策略 execution
  • (强烈推荐)移动端音视频从零到上手(下)
  • (转)关于多人操作数据的处理策略
  • (轉貼)《OOD启思录》:61条面向对象设计的经验原则 (OO)
  • (总结)Linux下的暴力密码在线破解工具Hydra详解
  • .locked1、locked勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .net 流——流的类型体系简单介绍
  • .net经典笔试题
  • .NET是什么
  • .net下的富文本编辑器FCKeditor的配置方法
  • .sh文件怎么运行_创建优化的Go镜像文件以及踩过的坑
  • /etc/skel 目录作用
  • @javax.ws.rs Webservice注解
  • @JsonSerialize注解的使用
  • @RequestBody与@ModelAttribute
  • [22]. 括号生成
  • [bzoj1006]: [HNOI2008]神奇的国度(最大势算法)
  • [C#]无法获取源 https://api.nuge t.org/v3-index存储签名信息解决方法