并发编程之创建线程和线程的状态

news2024/11/25 1:02:38

创建线程的三种方式

1.继承Thread类 重写run方法

class MyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName() + ":打了" + i + "个小兵");
        }
    }
}
public class Test {
    public static void main(String[] args) {
        //创建MyThread对象
        MyThread t1=new  MyThread();
        MyThread t2=new  MyThread();
        MyThread t3=new  MyThread();
        //设置线程的名字
        t1.setName("鲁班");
        t2.setName("刘备");
        t3.setName("亚瑟");
        //启动线程
        t1.start();
        t2.start();
        t3.start();
    }
}

2.实现eunnable 重写run方法

 class MyRunnable implements Runnable {

    public void run() {
        for (int i = 0; i < 10; i++) {
            try {//sleep会发生异常要显示处理
                Thread.sleep(20);//暂停20毫秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "打了:" + i + "个小兵");
        }
    }
}

public class Test {
    public static void main(String[] args) {

        //创建MyRunnable类
        MyRunnable mr = new MyRunnable();
        //创建Thread类的有参构造,并设置线程名
        Thread t1 = new Thread(mr, "张飞");
        Thread t2 = new Thread(mr, "貂蝉");
        Thread t3 = new Thread(mr, "吕布");
        //启动线程
        t1.start();
        t2.start();
        t3.start();

  
    }
}
class CallerTask implements Callable<String> {
    public String call() throws Exception {
        return "Hello,i am running!";
    }

    public static void main(String[] args) {
        //创建异步任务
        FutureTask<String> task=new FutureTask<String>(new CallerTask());
        //启动线程
        new Thread(task).start();
        try {
            //等待执行完成,并获取返回结果
            String result=task.get();
            System.out.println(result);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

注意!!:以上两种方式都是要调用start方法,才能真正实现多线程。直接调用run相当于调用普通方法

线程状态

// Thread.State 源码
public enum State {
    NEW,
    RUNNABLE,
    BLOCKED,
    WAITING,
    TIMED_WAITING,
    TERMINATED;
}

NEW状态

表示线程已经被创建,但是还未被启动

测试在start之前调用getState查看状态,是NEW

  Thread t1 = new Thread(mr, "张飞");
        Thread t2 = new Thread(mr, "貂蝉");
        Thread t3 = new Thread(mr, "吕布");
        System.out.println(t1.getState());

        //启动线程
        t1.run();

Runnable状态

表示当前线程正在运行中。处于 RUNNABLE 状态的线程在 Java 虚拟机中运行,也有可能在等待 CPU 分配资源。

在操作系统层面,线程状态包括ready和running,但是在JVM层面,只能看到Runnable状态,也就是将这两种状态统称为Runnable(运行中)。

Runnable状态可以由NEW状态调用start方法转变过来,但是:

  1. 反复调用同一个线程的 start 方法不可行,回抛出异常
  2. 假如一个线程执行完毕(此时处于 TERMINATED 状态),再次调用这个线程的 start 方法也不可行

看下面的start代码,每次进入会判断threadStatus变量,这个变量代表当前线程的状态。如果线程已经启动或者已经终止,threadStatus就不等于0,进入start就会 throw  IllegalThreadStateException();

// 使用synchronized关键字保证这个方法是线程安全的
public synchronized void start() {
    // threadStatus != 0 表示这个线程已经被启动过或已经结束了
    // 如果试图再次启动这个线程,就会抛出IllegalThreadStateException异常
    if (threadStatus != 0)
        throw new IllegalThreadStateException();

    // 将这个线程添加到当前线程的线程组中
    group.add(this);

    // 声明一个变量,用于记录线程是否启动成功
    boolean started = false;
    try {
        // 使用native方法启动这个线程
        start0();
        // 如果没有抛出异常,那么started被设为true,表示线程启动成功
        started = true;
    } finally {
        // 在finally语句块中,无论try语句块中的代码是否抛出异常,都会执行
        try {
            // 如果线程没有启动成功,就从线程组中移除这个线程
            if (!started) {
                group.threadStartFailed(this);
            }
        } catch (Throwable ignore) {
            // 如果在移除线程的过程中发生了异常,我们选择忽略这个异常
        }
    }
}

BLOCK

阻塞状态。处于 BLOCKED 状态的线程正等待锁的释放以进入同步区。

WAITING

等待状态。处于等待状态的线程变成 RUNNABLE 状态需要其他线程唤醒。

BLOCK和WAITING有哈区别?

TIMED_WAITING

TIMED_WAITING(超时等待) 状态相当于在等待状态的基础上增加了超时限制,比如通过 sleep(long millis)方法或 wait(long millis)方法可以将线程置于 TIMED_WAITING 状态。当超时时间结束后,线程将会返回到 RUNNABLE 状态。

线程状态的转变

线程状态转换图

 

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

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

相关文章

QT学习笔记-QT5.15编译及安装谷歌拼音输入法(QtInputMethod_GooglePinyin)

QT学习笔记-QT5.15编译及安装谷歌拼音输入法&#xff08;QtInputMethod_GooglePinyin&#xff09; 0、背景1、环境2、下载QtInputMethod_GooglePinyin源码3、使用MinGW64构建套件编译3.1 编译QtInputMethod_GooglePinyin源码3.2、部署tgtsmlInputContextPlugin输入法插件3.3、运…

uniapp安卓ios打包上线注意事项

1、安卓包注意事项 隐私政策弹框提示 登录页面隐私政策默认不勾选隐私政策同意前不能获取用户权限APP启动时&#xff0c;在用户授权同意隐私政策前&#xff0c;APP及SDK不可以提前收集和使用IME1、OAID、IMS1、MAC、应用列表等信息 ios包注意事项 需要有注销账号的功能 3、安…

人工智能(一)基本概念

人工智能之基本概念 常见问题什么是人工智能&#xff1f;人工智能应用在那些地方&#xff1f;人工智能的三种形态图灵测试是啥&#xff1f;人工智能、机器学习和深度学习之间是什么关系&#xff1f;为什么人工智能计算会用到GPU&#xff1f; 机器学习什么是机器学习&#xff1f…

财务报表数据,你看懂了吗?

之前分享过一期&#xff0c;财务数据哪里找&#xff1f;现在当我们找到相应数据&#xff0c;那我们得了解这些数据代表什么&#xff0c;能否看懂这些下载的报告&#xff0c;无论对于企业还是高校、科研所都是很重要的。如果看不懂&#xff0c;就像是站在门外的人&#xff0c;拿…

((*(volatile unsigned long *) (reg)))

#define LONGREG(reg) ((*(volatile unsigned long *) (reg)))1.&#xff08;unsigned long *&#xff09;(reg) 代表“reg”是1个unsigned long类型的指针&#xff1b; volatile是一个修饰符&#xff0c;告诉编译器此段代码不要优化,确保本条指令不会因C 编译器的优化而被省…

安装部署docker以及基本的操作

目录 一.安装与部署docker 1.1 关闭防火墙 1.2 安装依赖包 1.3 设置阿里云镜像源 1.4安装docker-ce社区版 二.设置镜像加速 三.网络优化 四.docker镜像操作 4.1 搜索镜像——docker search 镜像 4.2 下载镜像——docker pull 仓库名/镜像名&#xff1a;标签 4.3 查看已下载…

成集云 | 鼎捷ERP采购单同步钉钉 | 解决方案

源系统成集云目标系统 方案介绍 鼎捷ERP&#xff08;Enterprise Resource Planning&#xff09;是一款综合性的企业管理软件&#xff0c;它包括了多个模块来管理企业的各个方面&#xff0c;其中之一就是采购订单模块。鼎捷ERP的采购订单模块可以帮助企业有效管理和控制采购过程…

JavaScript 第二天

深入对象内置构造函数 一. 深入对象 创建对象三种方式构造函数实例成员&静态成员 1.1 创建对象三种方式 ① 利用对象字面量创建对象 const o {name: 哈哈 } ② 利用new Object 创建对象 const o new Object({ name: 哈哈 }) ③ 构造函数创建对象 1.2 构造函数 …

C进阶(2/7)前篇——指针进阶

前言&#xff1a;本文章讲解部分指针进阶内容。后续继续更新。 文章重点&#xff1a; 1. 字符指针 2. 数组指针 3. 指针数组 4. 数组传参和指针传参 目录 前言&#xff1a;本文章讲解部分指针进阶内容。后续继续更新。 指针初阶了解&#xff1a; 1.字符指针 1.1一道有关于字…

day8 STM32数据搬运工 - DMA

DMA简介 DMA&#xff0c;全称为&#xff1a;Direct Memory Access&#xff0c;即直接存储器访问。 DMA 传输方式无需 CPU 直接控制传输&#xff0c;也没有中断处理方式那样保留现场和恢复现场的过程&#xff0c;通过硬件为 RAM 与 I/O 设备开辟一条直接传送数据的通路&#x…

(二)掌握最基本的Linux服务器用法——Linux下简单的C/C++ 程序、项目编译

1、静态库与动态库 静态库(Static Library)&#xff1a;静态库是编译后的库文件&#xff0c;其中的代码在编译时被链接到程序中&#xff0c;因此它会与程序一起形成一个独立的可执行文件。每个使用静态库的程序都会有自己的库的副本&#xff0c;这可能会导致内存浪费。常用后缀…

Mendix 基础审计模块介绍

一、前言 作为售前顾问&#xff0c;帮助客户选型低代码产品是日常工作。考察一家低代码产品的好坏&#xff0c;其中一个维度就是产品的成熟度。产品成熟度直接影响产品在使用中的稳定性和用户体验&#xff0c;对于新工具导入和可持续运用至关重要。 那怎么考察一个产品是否成…

Ghost-free High Dynamic Range Imaging withContext-aware Transformer

Abstract 高动态范围(HDR)去鬼算法旨在生成具有真实感细节的无鬼HDR图像。 受感受野局部性的限制&#xff0c;现有的基于CNN的方法在大运动和严重饱和度的情况下容易产生重影伪影和强度畸变。 本文提出了一种新的上下文感知视觉转换器&#xff08;CA-VIT&#xff09;用于高动态…

UNIAPP中开发企业微信小程序

概述 需求为使用uni-app开发企业微信小程序。希望可以借助现成的uni-app框架&#xff0c;快速开发。遇到的问题是uni-app引入jweixin-1.2.0.js提示异常: Reason: TypeError: Cannot read properties of undefined (reading ‘title’)。本文中描述了如何解决该问题&#xff0c…

Python语法基础——循环

学习目标 通过使用while循环编写重复执行的语句。遵从循环的设计策略开发循环。利用用户的确认控制循环。用哨兵值控制循环。通过使用输入重定向从文件获取大量数据而不是从键盘输入来来获取大量数据&#xff0c;并且使用输出重定向将输出存人文件。使用for循环来实现计数器控制…

【资料包】HDC.Together 2023精选Codelabs指南现已上线(内有活动)

今年HDC.Together 2023的Codelabs挑战系列活动如期而至&#xff0c;众多开发者齐聚一堂&#xff0c;积极参与。本次赛题中部分Codelabs已在官网上线详细操作指南&#xff0c;让我们与众多coders一起探索代码的独特魅力。 01 ArkTS基础知识&#xff08;ArkTS&#xff09; 本课程…

Spring系列六:JdbcTemplate

&#x1f992;JdbcTemplate &#x1f4d5;实际需求 实际需求: 如果程序员就希望使用spring框架来做项目, spring框架如何处理对数据库的操作呢? 方案1: 使用前面做项目开发的JdbcUtils类方案2: 其实spring提供了一个操作数据库(表)功能强大的类JdbcTemplate. 我们可以同ioc…

目标和——力扣494

文章目录 题目描述解法:动态规划题目描述 解法:动态规划 nt findTargetSumWays(vector<int>& nums, int target){int sum

Paper 推荐第3期|隐私集合求交 PSI 系列

前言&#xff1a; 隐语 awesome-PETs&#xff08;PETs即Privacy-Enhancing Technologies &#xff0c;隐私增强技术&#xff09;精选业内优秀论文&#xff0c;按技术类型进行整理分类&#xff0c;旨在为隐私计算领域的学习研究者提供一个高质量的学习交流社区。awesome-PETs 包…

关于vant2 组件van-dropdown-item,在IOS手机上,特定条件下无法点击问题的探讨

情景重现 先贴有问题的代码 <template><div :class"showBar ? homeContain : homeContain-nobar"><div class"contant" id"content"><van-dialog v-model"loading" :before-close"onBeforeClose" :…