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

多线程 start 和 run 方法到底有什么区别?

昨天栈长介绍了《Java多线程可以分组,还能这样玩!》线程分组的妙用。今天,栈长会详细介绍 Java 中的多线程 start() 和 run() 两个方法,Java 老司机请跳过,新手或者对这两个不是很理解的可以继续往下看。

首先要知道实现多线程最基本的两种方式:

1、继承 java.lang.Thread 类;

2、实现 java.lang.Runnable接口;

其中 Thread 类也是实现了 Runnable 接口,而 Runnable 接口定义了唯一的一个 run() 方法,所以基于 Thread 和 Runnable 创建多线程都需要实现 run() 方法,是多线程真正运行的主方法。

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

而 start() 方法则是 Thread 类的方法,用来异步启动一个线程,然后主线程立刻返回。该启动的线程不会马上运行,会放到等待队列中等待 CPU 调度,只有线程真正被 CPU 调度时才会调用 run() 方法执行。

所以 start() 方法只是标识线程为就绪状态的一个附加方法,以下 start() 方法的源码,其中 start0() 是一个本地 native 方法。

public synchronized void start() {
    if (threadStatus != 0)
        throw new IllegalThreadStateException();

    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 */
        }
    }
}

请注意,start() 方法被标识为 synchronized 的,即为了防止被多次启动的一个同步操作。

那么你会问了,为什么要有两个方法,直接用一个 run() 方法不就行了吗!? 还真不行,如果直接调用 run() 方法,那就等于调用了一个普通的同步方法,达不到多线程运行的异步执行,来看下面的例子。

/**
 * 微信公众号:Java技术栈
 */
public static void main(String[] args) {
    Thread thread = new Thread(() -> {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Java技术栈");
    });

    long start = System.currentTimeMillis();
    thread.start();
    System.out.println(System.currentTimeMillis() - start);

    start = System.currentTimeMillis();
    thread.run();
    System.out.println(System.currentTimeMillis() - start);
}

程序输出:

0
Java技术栈
3000
Java技术栈

从程序输出结果可以看出,启动 start 方法前后只用了 0 毫秒,而启动 run 方法则阻塞了 3000 毫秒等程序执行完再继续执行,这就是同步与异步的一个最重要的区别。

看完这篇,你应该对 start 和 run 方法有了一个大概的掌握吧,再也不怕面试官问你这两个的区别了吧!

动手转发给更多的朋友吧!


更多 Java 多线程技术文章请在Java技术栈微信公众号后台回复关键字:多线程。

本文原创首发于微信公众号:Java技术栈(id:javastack),关注公众号在后台回复 "多线程" 可获取更多,转载请原样保留本信息。

相关文章:

  • MongoDB----逻辑与物理存储结构
  • 2018北京理工大学区块链技术讲座
  • ide phpStorm 配置PHP路径并本地执行PHP脚本
  • [2018/11/18] Java数据结构(2) 简单排序 冒泡排序 选择排序 插入排序
  • taro 填坑之路(三)taro 缓存
  • deepin bashrc 文件修改后恢复方法
  • Python函数的基础知识
  • 【许晓笛】 EOS 智能合约案例解析(3)
  • 关于智能共享出行,政界、学界和业界的专家都说了什么? | SMC 2018
  • vue-cli 打包编译 -webkit-box-orient: vertical 被删除解决办法
  • django发送邮件
  • mysql如何设置两个默认时间列
  • Linux运维命令总结
  • 统计学习方法概论---泛化能力
  • 8年软件测试工程师感悟——写给还在迷茫中的朋友
  • 345-反转字符串中的元音字母
  • Android优雅地处理按钮重复点击
  • CSS3 聊天气泡框以及 inherit、currentColor 关键字
  • Eureka 2.0 开源流产,真的对你影响很大吗?
  • JavaScript HTML DOM
  • JavaScript 基本功--面试宝典
  • JavaScript工作原理(五):深入了解WebSockets,HTTP/2和SSE,以及如何选择
  • Java知识点总结(JavaIO-打印流)
  • quasar-framework cnodejs社区
  • SQL 难点解决:记录的引用
  • TiDB 源码阅读系列文章(十)Chunk 和执行框架简介
  • underscore源码剖析之整体架构
  • vue2.0开发聊天程序(四) 完整体验一次Vue开发(下)
  • vue--为什么data属性必须是一个函数
  • 更好理解的面向对象的Javascript 1 —— 动态类型和多态
  • 近期前端发展计划
  • 马上搞懂 GeoJSON
  • 实现菜单下拉伸展折叠效果demo
  • 移动互联网+智能运营体系搭建=你家有金矿啊!
  • 主流的CSS水平和垂直居中技术大全
  • 选择阿里云数据库HBase版十大理由
  • !!java web学习笔记(一到五)
  • #单片机(TB6600驱动42步进电机)
  • #我与Java虚拟机的故事#连载04:一本让自己没面子的书
  • #我与Java虚拟机的故事#连载18:JAVA成长之路
  • $NOIp2018$劝退记
  • (2)STM32单片机上位机
  • (23)Linux的软硬连接
  • (C++17) std算法之执行策略 execution
  • (done) ROC曲线 和 AUC值 分别是什么?
  • (Matlab)遗传算法优化的BP神经网络实现回归预测
  • (笔试题)分解质因式
  • (未解决)jmeter报错之“请在微信客户端打开链接”
  • (转)Scala的“=”符号简介
  • ../depcomp: line 571: exec: g++: not found
  • .Net 8.0 新的变化
  • .net core MVC 通过 Filters 过滤器拦截请求及响应内容
  • .net core 实现redis分片_基于 Redis 的分布式任务调度框架 earth-frost
  • .NET MAUI学习笔记——2.构建第一个程序_初级篇
  • .NET 除了用 Task 之外,如何自己写一个可以 await 的对象?