• 解析java中创建并运行线程的三种方式


    解析java中创建并运行线程的三种方式

    1 继承Thread类

    1.1 核心思路

    1.1.1 写一个自定义类继承(extends) Thread类

    1.1.2 重写Run方法,里面写线程执行过程中的业务逻辑

    1.1.3 实例化自定义类,得到对象a(创建了一个线程,new的状态)

    1.1.4 a.start()方法去启动线程(ready状态---->就绪)

    1.2 示例代码

    Cat类

    package Work4;
    public class Cat extends Thread{
        /*一定要重写Thread类里面的Run方法
         因为不写的话默认就是调用父类型特征区里面的run方法
        我们创建并启动线程,是需要写自己独有的业务逻辑,因此就必须重写它
        这个地方不重写也不会报错,因此需要特别关注一下
         */
        @Override
        public void run() {
            int count=0;
            while(count<10){
                System.out.println("线程名"+Thread.currentThread().getName()+"的小猫咪正在喵喵喵"+(++count));
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    ThreadTest类

    package Work4;
    
    public class ThreadTest {
        public static void main(String[] args) {
            Cat cat=new Cat();
            cat.start();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    1.3 示例代码运行截图

    在这里插入图片描述

    2 实现Runnable接口

    2.1 核心思路

    2.1.1 写一个自定义类实现Runnable接口

    2.1.2 重写Runnable接口的run方法,书写线程自己的业务逻辑

    2.1.3 实例化自定义类,得到对象a

    2.1.4 实例化Thread类,在实例化的过程中把对象a通过构造方法(Runnable target)传入进去,得到对象t

    2.1.5 t.start()方法

    2.2 示例代码

    Cat类

    package Work4;
    public class Cat implements Runnable{
        @Override
        public void run() {
            int count=0;
            while(count<10){
                System.out.println("线程名"+Thread.currentThread().getName()+"的小猫咪正在喵喵喵"+(++count));
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    ThreadTest类

    package Work4;
    
    public class ThreadTest {
        public static void main(String[] args) {
            //实例化自定义类,该类实现了Runnable接口
            Cat cat=new Cat();
            //实例化Thread类(线程类),在实例化的过程中将cat对象传入进去
            Thread thread = new Thread(cat);
            thread.start();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2.3 示例代码运行截图

    在这里插入图片描述

    3 匿名内部类实现

    3.1 核心思路

    3.1.1 实例化一个Thread类,得到对象t

    3.1.2 在实例化的过程中传入一个匿名类,该类实现了Runnable接口

    3.1.3 t.start()方法

    3.2 示例代码

    ThreadTest类

    package Work4;
    
    public class ThreadTest {
        public static void main(String[] args) {
           //采用匿名内部类的方式
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    int count=0;
                    while(count<10){
                        System.out.println("线程名"+Thread.currentThread().getName()+"的小猫咪正在喵喵喵"+(++count));
                    }
                }
            });
            thread.start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    3.3 示例代码运行截图

    在这里插入图片描述

    4 总结

    4.1 这三种方法都是和Thread类有关,都一定要重写run方法,在run方法里面写入自己的业务逻辑

    4.2 可以用run方法启动线程吗?

    4.2.1 分析

    不能,去调用run方法的过程中本质上就是调用一个普通方法,启动线程的方法是start方法,他在底层调用了start0方法(启动线程的关键方法)

    4.2.2 底层源码

     public synchronized void start() {
            /**
             * This method is not invoked for the main method thread or "system"
             * group threads created/set up by the VM. Any new functionality added
             * to this method in the future may have to also be added to the VM.
             *
             * A zero status value corresponds to state "NEW".
             */
            if (threadStatus != 0)
                throw new IllegalThreadStateException();
    
            /* Notify the group that this thread is about to be started
             * so that it can be added to the group's list of threads
             * and the group's unstarted count can be decremented. */
            group.add(this);
    
            boolean started = false;
            try {
                start0();
                //本质是这个方法启动了线程
                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 */
                }
            }
        }
    
        private native void start0();
    //被native修饰的方法代表是用c/c++实现的代码
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    4.3 使用继承Thread类这种方式去创建并启动线程,一定要重写run方法,不可忘记,因为你不重写它也不会有任何提示

    4.4 一般来说,使用实现Runnable接口的方法去创建并启动线程用到比较多,我们写程序也应该首选它,因为它能有效避免java单继承的缺点

  • 相关阅读:
    FreeRTOS 延时函数和软件定时器 详解
    类和对象1:基础学习
    Maven的使用
    基于springboot实现职称评审管理系统演示【项目源码+论文说明】分享
    React高频面试题100+题,这一篇就够了!
    吐血推荐17个提升开发效率的“轮子”
    MAC 通过IDEA启动tomcat,显示80端口被占用解决办法
    单元测试 —— JUnit 5 参数化测试
    极市直播丨南京理工大学魏秀参、沈阳:大规模细粒度图像检索
    WOODWARD 5466-318 是否打算转向开放的工业以太网协议
  • 原文地址:https://blog.csdn.net/SSS4362/article/details/126240332