【多线程】初识线程,基础了解

这篇具有很好参考价值的文章主要介绍了【多线程】初识线程,基础了解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

认识线程

    概念

        什么是线程?

        为啥要有线程

        进程和线程的区别

        Java 的线程 和 操作系统线程 的关系

    创建线程

        1.继承 Thread 类

        2.实现 Runnable 接口

        3.通过匿名内部类方式创建Thread与实现Runnable

       4.Lmabda表达式

Thread 类及常见方法

    Thread 的常见构造方法

     Thread 的几个常见属性

    启动一个线程-start()

    中断一个线程

    等待一个线程-join()

     获取当前线程引用

    休眠当前线程

线程的状态

    观察线程的所有状态


认识线程

    概念

        什么是线程?

一个线程就是一个 " 执行流 ". 每个线程之间都可以按照顺讯执行自己的代码 . 多个线程之间 " 同时 " 执行着多份代码。
多进程可以处理一个很大或复杂的任务,但启动进程时申请内存,申请文件资源,进程结束时释放文件,释放内存的操作非常耗时。
为了解决资源消耗问题,提出一个轻量化进程的概念(线程),创建线程时只关注要处理的任务,使用的是进程创建时申请的所有资源(类比开工厂)。
例:进程就相当于开工厂新建一个场子,需要购买地皮、拉电拉水、修建仓库等,非常的费时间;线程就相当于在原有工厂资源的基础上重新开一条生产线,不需要前期的资源申请,节省时间,更好的利用资源。

        为啥要有线程

首先 , " 并发编程 " 成为 " 刚需 ".
  • 单核 CPU 的发展遇到了瓶颈. 要想提高算力, 就需要多核 CPU. 而并发编程能更充分利用多核 CPU资源.
  • 有些任务场景需要 "等待 IO", 为了让等待 IO 的时间能够去做一些其他的工作, 也需要用到并发编程.
其次 , 虽然多进程也能实现 并发编程 , 但是线程比进程更轻量 .
  • 创建线程比创建进程更快.
  • 销毁线程比销毁进程更快.
  • 调度线程比调度进程更快.
最后 , 线程虽然比进程轻量 , 但是人们还不满足 , 于是又有了 " 线程池 "(ThreadPool) " 协程 "
(Coroutine)

        进程和线程的区别

  • 进程是包含线程的. 每个进程至少有一个线程存在,即主线程。
  • 进程和进程之间不共享内存空间. 同一个进程的线程之间共享同一个内存空间.
  • 进程是系统分配资源的最小单位,线程是系统调度的最小单位。

        Java 的线程 和 操作系统线程 的关系

线程是操作系统中的概念 . 操作系统内核实现了线程这样的机制 , 并且对用户层提供了一些 API 供用户使用( 例如 Linux pthread ).
Java 标准库中 Thread 类可以视为是对操作系统提供的 API 进行了进一步的抽象和封装 .

    创建线程

        1.继承 Thread

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

class MyThread extends Thread{
    @Override
    public void run() {
        System.out.println("这是线程运行代码");
    }
}

        2.实现 Runnable 接口

public class MRunnable {
    public static void main(String[] args) {
        MyRunnable runnable = new MyRunnable();
        Thread thread = new Thread(runnable);
        thread.start();
    }
}

class MyRunnable implements Runnable{
    @Override
    public void run() {
        System.out.println("这是线程运行代码");
    }
}

使用Runnable定义的好处:

  • 解耦,把定义线程与定义任务分开,以便修改代码统一修改
对比上面两种方法 :
  • 继承 Thread , 直接使用 this 就表示当前线程对象的引用.
  • 实现 Runnable 接口, this 表示的是 MyRunnable 的引用. 需要使用 Thread.currentThread()

        3.通过匿名内部类方式创建Thread与实现Runnable

Thread

public class Thread_Anon {
    public static void main(String[] args) {
        Thread thread = new Thread(){
            @Override
            public void run() {
                System.out.println("这是线程运行代码");
            }
        };
        thread.start();
    }
}

Runnable

public class Runnable_Anon {
    public static void main(String[] args) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("这是线程执行代码");
            }
        });
        thread.start();
    }
}

       4.Lmabda表达式

public class lambda {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            System.out.println("这是线程执行代码");
        });
        thread.start();
    }
}


用Lambda表达式实现的接口必须是函数式接口(接口中只有一个没有实现的方法)
使用多线程编程主要是为了充分利用CPU资源,提升程序运行效率;
但并不是所有场景使用多线程都可以提高效率

Thread 类及常见方法

Thread 类是 JVM 用来管理线程的一个类,换句话说,每个线程都有一个唯一的 Thread 对象与之关联。
每个执行流,也需要有一个对象来描述,而 Thread 类的对象就是用来描述一个线程执行流的,JVM 会将这些 Thread 对象组织起来,用于线程调度,线程管理。

    Thread 的常见构造方法

【多线程】初识线程,基础了解

     Thread 的几个常见属性

属性
获取方法
ID getId()
名称 getName()
状态 getState()
优先级 getPriority()
是否后台线程 isDaemon()
是否存活 isAlive()
是否被中断 isInterrupted()
  • ID 是线程的唯一标识,不同线程不会重复
  • 名称是各种调试工具用到
  • 状态表示线程当前所处的一个情况
  • 优先级高的线程理论上来说更容易被调度到
  • 关于后台线程,需要记住一点:JVM会在一个进程的所有非后台线程结束后,才会结束运行。
  • 是否存活,即简单的理解,为 run 方法是否运行结束了
  • 线程的中断问题

    启动一个线程-start()

之前我们已经看到了如何通过覆写 run 方法创建一个线程对象,但线程对象被创建出来并不意味着线程就开始运行了。
  覆写 run 方法是提供给线程要做的事情的指令清单
  线程对象可以认为是把 李四、王五叫过来了
  而调用 start() 方法,就是喊一声: 行动起来! ,线程才真正独立去执行了。
调用 start 方法 , 才真的在操作系统的底层创建出一个线程 .

    中断一个线程

李四一旦进到工作状态,他就会按照行动指南上的步骤去进行工作,不完成是不会结束的。但有时我们需要增加一些机制,例如老板突然来电话了,说转账的对方是个骗子,需要赶紧停止转账,那张三该如何通知李四停止呢?这就涉及到我们的停止线程的方式了。
目前常见的有以下两种方式:
  1. 通过共享的标记来进行沟通
  2. 调用 interrupt() 方法来通知
public class ThreadDemo {
    private static class MyRunnable implements Runnable {
        @Override
        public void run() {
            // 两种方法均可以
            while (!Thread.interrupted()) {
                //while (!Thread.currentThread().isInterrupted()) {
                System.out.println(Thread.currentThread().getName()
                        + ": 别管我,我忙着转账呢!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    System.out.println(Thread.currentThread().getName()
                            + ": 有内鬼,终止交易!");
                    // 注意此处的 break
                    break;
                }
            }
            System.out.println(Thread.currentThread().getName()
                    + ": 啊!险些误了大事");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MyRunnable target = new MyRunnable();
        Thread thread = new Thread(target, "李四");
        System.out.println(Thread.currentThread().getName()
                + ": 让李四开始转账。");
        thread.start();
        Thread.sleep(10 * 1000);
        System.out.println(Thread.currentThread().getName()
                + ": 老板来电话了,得赶紧通知李四对方是个骗子!");
        thread.interrupt();
    }
}

【多线程】初识线程,基础了解

 thread 收到通知的方式有两种:

1. 如果线程因为调用 wait/join/sleep 等方法而阻塞挂起,则以 InterruptedException 异常的形式通
知, 清除中断标志
  • 当出现 InterruptedException 的时候 , 要不要结束线程取决于 catch 中代码的写法 . 可以选择
    忽略这个异常 , 也可以跳出循环结束线程 .
2. 否则,只是内部的一个中断标志被设置, thread 可以通过
  • Thread.interrupted() 判断当前线程的中断标志被设置,清除中断标志
  • Thread.currentThread().isInterrupted() 判断指定线程的中断标志被设置,不清除中断标志

    等待一个线程-join()

有时,我们需要等待一个线程完成它的工作后,才能进行自己的下一步工作。例如,张三只有等李四转账成功,才决定是否存钱,这时我们需要一个方法明确等待线程的结束。

【多线程】初识线程,基础了解

     获取当前线程引用

方法
说明
public static Thread currentThread();
返回当前线程对象的引用

    休眠当前线程

因为线程的调度是不可控的,所以,这个方法只能保证实际休眠时间是大于等于参数设置的休眠时间的。
方法
说明
public static void sleep(long millis) throws InterruptedException
休眠当前线程 millis
毫秒
public static void sleep(long millis, int nanos) throws
InterruptedException
可以更高精度的休眠

线程的状态

    观察线程的所有状态

线程的状态是一个枚举类型 Thread.State
public class ThreadState {
    public static void main(String[] args) {
        for (Thread.State state : Thread.State.values()) {
            System.out.println(state);
        }
    }
}
  • NEW: 安排了工作, 还未开始行动
  • RUNNABLE: 可工作的. 又可以分成正在工作中和即将开始工作.
  • BLOCKED: 这几个都表示排队等着其他事情
  • WAITING: 这几个都表示排队等着其他事情
  • TIMED_WAITING: 这几个都表示排队等着其他事情
  • TERMINATED: 工作完成了.

【多线程】初识线程,基础了解

 

这里只是线程的部分知识,剩下的知识总结我会后面继续发布,期待大家关注文章来源地址https://www.toymoban.com/news/detail-436721.html

到了这里,关于【多线程】初识线程,基础了解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Kubernetes】 从基础认识 k8s核心pod相关概念

    提示:此篇帮助朋友们,养成从0到1不断延伸知识的一种方法 最简单的创建pod入手 访问官方文档,直接使用案例,进行修改即可! 官网地址:https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/assign-pods-nodes/ 删除不需要的部分,根据规则添加需要的参数即可得到需要的,代码如

    2024年01月25日
    浏览(69)
  • 初识React: 基础(概念 特点 高效原因 虚拟DOM JSX语法 组件)

    React是一个由Facebook开源的JavaScript库,它主要用于构建用户界面。React的特点是使用组件化的思想来构建界面,使得代码的可复用性和可维护性大大提高。React还引入了虚拟DOM的概念,减少了对真实DOM的直接操作,加快了渲染速度。 React使用虚拟DOM,将页面的渲染操作转化为

    2024年02月14日
    浏览(56)
  • TCP基础概念了解

    TCP(传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议,它完成第四层传输层所指定的功能。 TCP 协议的特点是: 面向连接:一定是「一对一」才能连接,不能像 UDP 协议可以一个主机同时向多个主机发送消息,也就是一对多是无法做到的。 可靠交付

    2024年02月04日
    浏览(43)
  • Node基础概念,先了解一下

    Nodejs是基于Chrome V8引擎的服务器端JavaScript运行环境,也就是说可以在浏览器之外的主机上运行JavaScript。 Nodejs有三部分组成:标准库、中间层和底层库。 标准库:是给开发人员直接调用的API,比如HTTP模块; 中间层:为什么要有中间层呢?主要是因为NodeJS底层采用C语言来实现

    2024年02月07日
    浏览(37)
  • Kafka - 深入了解Kafka基础架构:Kafka的基本概念

    我们首先了解一些Kafka的基本概念。 1)Producer :消息生产者,就是向kafka broker发消息的客户端 2)Consumer :消息消费者,向kafka broker获取消息的客户端 3)Consumer Group (CG):消费者组,由多个consumer组成。消费者组内每个消费者负责消费不同分区的数据,一个broker可以有多个

    2024年02月08日
    浏览(38)
  • 【postgresql 基础入门】从了解数据库访问权限,访问数据库,到认识数据库的所有者及属性,从此打开了数据库使用的大门

    ​ 专栏内容 : postgresql内核源码分析 手写数据库toadb 并发编程 ​ 开源贡献 : toadb开源库 个人主页 :我的主页 管理社区 :开源数据库 座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物. 入门准备 postgrersql基础架构 快速使用 初始化集群 数据库服务管理 psql客户

    2024年02月08日
    浏览(57)
  • 认识YOLOv5模型结构目录

    接上篇【文献解读】“MOBILEViT:轻量级、通用目的、移动友好的视觉变换器”。-CSDN博客 YOLOv5是一个流行的机器学习模型,用于目标检测任务。根据您希望提升或修改的内容,改进YOLOv5可以涉及多个方面: 模型架构(位于 /models ): 如果希望改变YOLOv5的架构,需要修改通常

    2024年01月21日
    浏览(36)
  • 认识ansible,了解常用的模块

    Ansible是一个基于Python开发的配置管理和应用部署工具,现在也在自动化管理领域大放异彩。它融合了众多老牌运维工具的优点,Pubbet和Saltstack能实现的功能,Ansible基本上都可以实现。 Ansible能批量配置、部署、管理上千台主机。比如以前需要切换到每个主机上执行的一或多个

    2024年02月21日
    浏览(33)
  • React框架课时二认识项目的结构目录一

    ├── README.md 使用方法的文档 ├── node_modules 所有的依赖安装的目录 ├── package-lock.json 锁定安装时的包的版本号,保证团队的依赖能保证一致。 ├── package.json ├── public 静态公共目录 └── src 开发用的源代码目录 2 图片的演示如图所示 README.md 使用方法的文档

    2024年02月02日
    浏览(78)
  • Linux多线程【初识线程】

    ✨个人主页: 北 海 🎉所属专栏: Linux学习之旅 🎃操作环境: CentOS 7.6 阿里云远程服务器 将一份代码成功编译后,可以得到一个可执行程序,程序运行后,相关代码和数据被 load 到内存中,并且操作系统会生成对应数据结构(比如 PCB )对其进行管理及分配资源,准备工作

    2024年02月12日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包