java基础之线程知识点

线程

进程的概念

操作系统(OS)中并发(同时)执行的多个程序任务

进程的特点

  • 宏观并行,微观串行

在一个时间段内,CPU会将时间段划分为若干个时间片,一个时间片是能被一个程序拥有,且只有拥有时间片的程序才能执行自身内容,所以当时间片的划分足够细小,交替频率足够快,就会形成并行的假象,时间上仍然是串行.

线程的概念

  • 是进程的基本组成部分

是进程中并发执行的多个任务

线程的特点

  • 宏观并行,微观串行

一个时间片只能被一个进程拥有,一个进程一次又只能执行一个线程. 由于进程之间交替执行,所以线程之间必定也是交替执行

多线程

  • 只存在多线程,不存在多进程

正在执行中的程序才叫进程,其他的都是等待执行的程序

无论是否拥有时间片,线程任务都叫线程

线程执行的组成

  1. 时间片

    • CPU调度分配, 线程争抢拥有

  2. 数据

    • 堆: 堆共享

    • 栈: 栈独立

  3. 代码

    • 书写逻辑

线程的创建

  1. 继承Thread, 重写run方法

    public class MyThread extends Thread {
        @Override
        public void run() {
            for (int i = 1; i <=100 ; i++) {
                System.out.println(i);
            }
        }
        
    }
    package com.by.test;
    ​
    import com.by.thread.MyThread;
    ​
    public class Test1 {
        public static void main(String[] args) {
            Thread t1 = new MyThread();
            Thread t2 = new MyThread();
    ​
            t1.start();
            t2.start();
            /*t1.run();
            t2.run();*/
    ​
            System.out.println("main结束");
        }
    }

  2. 实现Runnable,重写run方法. 在Thread对象的构造中传入任务对象

    package com.by.dao.impl;
    ​
    /**
     * 线程任务
     */
    public class MyRunnable implements Runnable{
        @Override
        public void run() {
            for (int i=1;i<=100;i++) {
                System.out.println(i);
            }
        }
    }
    package com.by.test;
    ​
    import com.by.dao.impl.MyRunnable;
    ​
    import javax.print.attribute.standard.RequestingUserName;
    ​
    public class Test2 {
        public static void main(String[] args) {
            /*//先创建任务对象
            Runnable r = new MyRunnable();
            //将任务对象传入线程对象
            Thread t1 = new Thread(r);*/
        //任务只会执行一次时,可以通过匿名内部类或者lambda简化书写
           Thread t1=new Thread(new Runnable() {
               @Override
               public void run() {
                   for (int i = 1; i <=100 ; i++) {
                       System.out.println("t1:: "+i);
                   }
               }
           });
    ​
           Thread t2=new Thread(()->{
                   for (int i = 101; i <=200 ; i++) {
                   System.out.println("t2> "+i);
               }
           });
    ​
            t1.start();
           t2.start();
    ​
    ​
        }
    }

更推荐使用第二种创建方式: 更符合类的单一职责,将线程对象的创建与线程任务的书写分离,更有利于后期的维护

使用

  1. 当开启多个线程之后, 线程之间会争抢时间片,拿到时间片的线程执行自身内容,其他线程无法执行,只能继续尝试争抢时间片,直到线程内容执行结束,才会脱离争夺队列

  2. 主函数也成为主线程,其一定是首个拥有时间片的线程

  3. 当开启多个线程之后,JVM执行结束的标志将从主函数执行结束转换为所有线程执行结束

  4. 开启线程需要调用线程对象.start()方法

线程状态

基础状态

等待状态

  • 也称为阻塞状态

  1. sleep()

    • Thread.sleep(毫秒数): 使当前线程释放自身时间片, 进入有限期休眠状态,在休眠时间内,该线程无法争抢时间片,休眠结束之后,才可以进入到就绪状态

      • 1秒=1000毫秒

    • 该方法需要处理非运行时异常, run方法不可上抛异常,所以必须通过try-catch处理解决

    Thread t1=new Thread(new Runnable() {
               @Override
               public void run() {
                   //让当前线程休眠3秒钟
                   try {
                       Thread.sleep(3000);
                   } catch (InterruptedException e) {
                       System.out.println("休眠异常");
                   }
                   for (int i = 1; i <=100 ; i++) {
                       System.out.println("t1:: "+i);
                   }
               }
           });

  2. join()

    • 线程对象.join(): 使调用者线程在当前线程之前执行, 当前线程只有等调用者线程执行结束进入死亡状态之后才有可能回到就绪状态.

    • 该方法需要处理非运行时异常,run方法无法上抛,必须通过try-catch处理

    package com.by.test;
    ​
    public class Test3 {
        public static void main(String[] args) {
            //以下代码执行顺序:t1->t2->t3
            Thread t1=new Thread(()->{
                for (int i = 0; i < 30; i++) {
                    System.out.println("t1:  "+i);
                }
            });
    ​
            Thread t2=new Thread(()->{
                //使t1线程在t2线程之前执行
                try {
                    t1.join();
                } catch (InterruptedException e) {
                    System.out.println("join失败");
                }
                for (int i = 101; i < 130; i++) {
                    System.out.println("t2>"+i);
                }
            });
    ​
            Thread t3=new Thread(()->{
                try {
                    t2.join();
                } catch (InterruptedException e) {
                    System.out.println("join失败");
                }
                for (char i = 65; i <=90; i++) {
                    System.out.println("t3::"+i);
                }
            });
    ​
    ​
            t1.start();
            t2.start();
            t3.start();
        }
    }

sleep和join的区别?

  1. sleep方法进入的是有限期等待状态,join方法进入的是无限期等待状态

  2. sleep是静态方法,可以直接通过类名调用,join是非静态方法,必须通过线程对象调用

线程池

前言: 当一个任务需要多次执行时,如果将任务放置于线程对象Thread中,会浪费内存空间导致不合理的并发,线程池可以解决该问题

作用

管理盛放线程任务, 将需要执行的任务提交执行,任务结束之后池与任务并不会立即销毁,任务对象会回到池中等待下次执行,直到线程池关闭,内部任务才会失效

创建-API

  1. ExecutorService: 线程池接口

    • submit(线程任务对象): 提交线程任务使其执行

    • shutdown(): 关闭线程池

  2. Executors: 线程池工具类,用来获取线程池对象

    • newCachedThreadPool(): 获取一个不固定并发数量的线程池对象

    • newFixedThreadPool(int ):获取一个固定并发数量的线程池对象

    不固定并发数量的线程池: 所有提交到池中的任务都会同时并发

    固定并发数量的线程池: 对应并发数量的任务先并发执行,超出的任务需要等待执行,等池中执行的任务结束让位之后,超出部分的任务才会进入池中执行

线程任务

  1. Runnable: run()

    • 无返回值,不能上抛异常

    package com.by.test;
    ​
    import com.by.dao.impl.MyRunnable;
    ​
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    ​
    public class Test4 {
        public static void main(String[] args) {
            //获取一个不固定并发数量的线程池
           // ExecutorService es1 = Executors.newCachedThreadPool();
            ExecutorService es1 = Executors.newFixedThreadPool(2);
    ​
            Runnable r1=new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 50; i++) {
                        System.out.println("r1>>"+i);
                    }
                }
            };
            Runnable r2=new Runnable() {
                @Override
                public void run() {
                    for (int i = 50; i < 100; i++) {
                        System.out.println("r2:::"+i);
                    }
                }
            };
            //提交任务执行
            es1.submit(r1);
            es1.submit(r2);
            es1.submit(r2);
    ​
            //关闭线程池
            es1.shutdown();
        }
    }

  2. Callable: call()

    • 有返回值,可以上抛异常,默认上抛Exception

    • 返回值会存放于一个Future对象中,可以通过Future对象.get()获取内部的返回值

    Callable<返回值类型> c1=new Callable<返回值类型>() {
                @Override
                public 返回值类型 call() throws Exception {
                   //...
                    return 值;
                }
            };
    package com.by.test;
    ​
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    ​
    public class Test5 {
        public static void main(String[] args) throws Exception {
            //创建线程池
            ExecutorService es = Executors.newCachedThreadPool();
            //线程任务1: 计算1-100的和并返回
            Callable<Integer> c1=new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    int sum=0;
                    for (int i = 0; i < 101; i++) {
                        sum += i;
                    }
                    return sum;
    ​
                }
            };
            //提交任务执行并接收
            Future<Integer> f =es.submit(c1);
            System.out.println(f.get());
    ​
            System.out.println(es.submit(c1).get());
    ​
            //关闭线程池
            es.shutdown();
        }
    }

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

9 - 数据分片概述|部署MyCat服务

数据分片概述&#xff5c;部署MyCat服务&#xff5c;测试配置 数据分片概述分库分表分割方式水平分割&#xff08;横向切分&#xff09;垂直分割&#xff08;纵向切分&#xff09; 提供分库分表存储服务软件&#xff08;中间件&#xff09;MyCAT软件分片服务器的工作过程 部署M…

[Kubernetes]10. k8s部署Goweb+mysql项目实战演练

一.安装docker构建镜像 如果要本地构建镜像的话,对应节点还需要安装docker,安装教程见:[Docker]一.Docker 简介与安装 linux环境,centos8下 docker及docker compose安装教程 k8s部署Goweb+mysql项目有两种方法:第一种是传统部署方法,第二种是通过ConfigMap实现应用配置分离部署…

OPenCV中的开闭运算

闭运算是先膨胀再腐蚀的过程&#xff0c;可以用来清除小黑点 开运算同理 开运算是先腐蚀再膨胀的过程&#xff0c;可以清除一些小两点和毛刺 闭运算和开运算使用不同大小的结构元素是因为它们的目标不同。 闭运算的目标是尽量消除小黑点&#xff0c;保持较大的连通区域。因此…

最佳利用Mock提升测试效率的7个技巧!

再聊这个问题之前&#xff0c;我们先了解一下公司技术架构的演变过程&#xff0c;这样我们才能真正体会到我们为什么要使用 Mock功能。 单体应用 在早期&#xff0c; 大部分公司的应用技术栈主要可以分为两大类&#xff1a;LAMP&#xff08;Linux Apache MySQL PHP&#x…

1.50A、0.75A、1.50A、1.20A电流控制型比例马达放大器

1.50A、0.75A、1.50A、1.20A、0.70A、0.60A、1.40A控制电流型比例阀、比例泵、比例马达放大器&#xff0c;带数显区显示及当前参数现场可调&#xff0c;如指令、电流、上下斜坡、颤振频率等&#xff1b; 模块式及插头式外观&#xff0c;可现场调试各种参数&#xff1b; 兼容多…

TortoiseGit 2.15.0.0 安装与配置(图文详细教程)

TortoiseGit的安装与配置 TortoiseGit是Tortoise为Git提供的版本可视化工具&#xff0c;简化了记忆Git命令行的过程&#xff0c;将命令行可视化。 确保自己电脑中已经下载好了git 官网下载TortoiseGit Download – TortoiseGit – Windows Shell Interface to Git 选择64-bi…

如何定位和优化程序CPU、内存等性能之巅

如何定位和优化程序CPU、内存等性能之巅 摘要 性能优化指在不影响系统运行正确性的前提下&#xff0c;使之运行得更快&#xff0c;完成特定功能所需的时间更短&#xff0c;或拥有更强大的服务能力。本文将介绍性能优化的基本概念以及如何定位和优化程序中的CPU、内存和IO瓶颈…

树形控件中的子项点击显示按钮弹窗

效果 MainWindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include"QStandardItemModel" QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACEclass MainWindow : public QMainWindow {Q_OBJECTpublic:Main…

学习怎么能从复杂的开始?,开始学一个个人博客吧

做一个个人博客第一步该怎么做&#xff1f; 好多零基础的同学们不知道怎么迈出第一步。 那么&#xff0c;就找一个现成的模板学一学呗&#xff0c;毕竟我们是高贵的Ctrl c v 工程师。 但是这样也有个问题&#xff0c;那就是&#xff0c;那些模板都&#xff0c;太&#xff01;…

(一)环境部署

Python虚拟环境 安装virtualenv pip install virtualenv 创建环境 virtualenv -p D:\python\python.exe(python解释器目录) env-py3.6(虚拟环境目录&#xff0c;名称随意) 在当前目录下生成env-py3.6目录。 激活环境 ...\env-py3.6\Scripts> .\activate 关闭&#xf…

mybatis中的驼峰转换

一、有啥用 开发时常用对象来存储从数据库中的记录&#xff0c;开启驼峰转化即可实现数据库字段(通常使用_下划线连接)与对象属性的对应&#xff0c;如数据库中的first_name字段会转化为firstName与对象中的firstName属性对应。 二、配置 三、相关报错 数据库字段与对象属性…

通过myBatis将sql语句返回的值自动包装成一个java对象(1)以及SqlSessionFactory

如果我们从数据库中读取了一个用户的两个属性——用户名和密码。此时我们希望把这两个属性放入一个java的用户对象中。我们可以选择new一个user对象&#xff0c;向构造器传入我们刚刚读取的两个属性。但一旦从数据库中读取的内容变多&#xff0c;我们就需要new很多新的对象。这…

艾瑞报告:HR数字化需关注体系化能力,红海云等标杆厂商引领一体化趋势

新全球化时代背景下&#xff0c;企业经营所面临的国内外环境的不确定性增强&#xff0c;如何从不确定性中找到确定性成了大多数企业的关注要点。近日&#xff0c;艾瑞咨询发布《2023中国人力资源数字化研究报告》&#xff0c;从数字化转型的角度切入&#xff0c;探讨数字化如何…

电池包的UL9540A,电池PACK的UL9540A,工商储的UL9540A,电芯的UL9540A,电池模组的UL9540A,家储的UL9540A

电池包的UL9540A,电池PACK的UL9540A,工商储的UL9540A&#xff0c;电芯的UL9540A&#xff0c;电池模组的UL9540A,家储的UL9540A UL9540A要求ESS在不同条件下进行测试&#xff0c;并要求满足特定的性能要求。测试包括热暴露测试、短路测试、过充电和过放电测试、外部影响测试等。…

[论文阅读]DeepFusion

DeepFusion Lidar-Camera Deep Fusion for Multi-Modal 3D Object Detection 用于多模态 3D 物体检测的激光雷达相机深度融合 论文网址&#xff1a;DeepFusion 论文代码&#xff1a;DeepFusion 摘要 激光雷达和摄像头是关键传感器&#xff0c;可为自动驾驶中的 3D 检测提供补…

ssh远程访问及控制

目录 一、ssh协议简介 1、实现远程访问的协议和程序 2、ssh协议的概念及功能 3、ssh协议的工作原理 3.1 对称加密与非对称加密 3.1.1 对称加密&#xff08;Symmetric Encryption&#xff09; 3.1.2 非对称加密&#xff08;Asymmetric Encryption&#xff09; 3.2 公钥传…

生物信息学导论-北大-马尔可夫模型

ref: https://www.coursera.org/learn/sheng-wu-xin-xi-xue/home 本文主要来自本课的讲义。 Markov Model markov链描述了一个在连续时间段的离散随机过程&#xff0c;其中从一个状态向其他状态&#xff08;包括自身&#xff09;的转换&#xff0c;是由一个概率分布&#xff…

RK3568驱动指南|驱动基础进阶篇-进阶8 内核运行ko文件总结

瑞芯微RK3568芯片是一款定位中高端的通用型SOC&#xff0c;采用22nm制程工艺&#xff0c;搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码&#xff0c;支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU&#xff0c;可用于轻量级人工…

LED 显示屏租赁特点及发展趋势大分析

LED租赁屏&#xff08;LED screen rental)作为一款专门用于舞台演出&#xff0c;文艺活动现场的LED显示屏&#xff0c;正逐渐成为户外广告传媒载体的首选。它广泛应用于舞台租赁、歌舞活动晚会、各种发布会、展会、体育场、剧场、礼堂、报告厅、多功能厅、会议室、演绎厅、迪吧…

JavaScript 入门手册

准备好快速学习 JavaScript了吗&#xff1f; 如果是&#xff0c;那么你需要这份 JavaScript 小抄。它以清晰、简洁和初学者友好的方式介绍了 JavaScript 的基础知识。 将它作为提高 JavaScript 技能的参考或指南。 让我们深入学习。 什么是 JavaScript&#xff1f; JavaSc…