java基础之线程知识点

news2024/11/19 3:45:16

线程

进程的概念

操作系统(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();
        }
    }

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

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

相关文章

keycloak部署

https://downloads.jboss.org/keycloak/11.0.2/keycloak-11.0.2.zip 1.上传zip 并解压 uzip keycloak-11.0.2.zip 2.创建mysql数据库 CREATE SCHEMA keycloak DEFAULT CHARACTER SET utf8 ; 3.安装mysql的jdbc驱动 下载mysql的JDBC驱动&#xff08;mysql-connector-java-8…

基于ssm的校园二手交易平台的设计与开发+vue论文

摘 要 社会和科技的不断进步带来更便利的生活&#xff0c;计算机技术也越来越平民化。二十一世纪是数据时代&#xff0c;各种信息经过统计分析都可以得到想要的结果&#xff0c;所以也可以更好的为人们工作、生活服务。二手物品是学校里最常见的物品&#xff0c;把二手物品再次…

sql | 学生参加各科考试次数

学生表: Students------------------------ | Column Name | Type | ------------------------ | student_id | int | | student_name | varchar | ------------------------ 在 SQL 中&#xff0c;主键为 student_id&#xff08;学生ID&#xff09;。 该表内的每…

海格里斯HEGERLS仓储货架生产厂家|载荷1.5T运行速度1.7~2m/s的智能四向穿梭车系统

四向穿梭车立体库是近年来出现的一种智能型密集系统&#xff0c;通过使用四向穿梭车在货架的水平和纵向轨道上运行来搬运货物&#xff0c;一台四向穿梭车就能完成货物的搬运工作&#xff0c;大大提高了工作效率。同时配合提升机、自动化仓库管理系统(WMS)和仓库调度系统(WCS)&a…

Express框架搭建项目

1. Express简介 EXpress&#xff1a; 精简的、灵活的Node.js Web程序框架&#xff0c;为构建单页、多页及混合的Web程序提供了一系列健壮的功能特性。 精简&#xff1a; Express在你的想法和服务器之间充当薄薄的一层&#xff0c;尽量少干预你&#xff0c;在你充分表达自己思…

v-if 实现不同的状态样式

目录 一、实现思路 二、实现步骤 案例一&#xff1a; ①view部分展示 ②JavaScript 内容 ④ 效果展示 案例二&#xff1a; ①view部分展示 ②JavaScript 内容 ④ 效果展示 ​编辑 一、实现思路 通过v-for循环获取数据并进行判断该条记录中status的状态 给不同的状态赋值&am…

引领安全创新 | 安全狗方案入选工信部《2023年工业和信息化领域数据安全典型案例名单》

近日&#xff0c;工业和信息化部网络安全管理局公布了2023年工业和信息化领域数据安全典型案例名单。 安全狗与厦门卫星定位应用股份有限公司、中移 (上海) 信息通信科技有限公司联合申报的智慧交通云数据安全与隐私保障典型案例也成功入选。 厦门服云信息科技有限公司&#xf…

WebStom中代码美化工具prettier的配置

如果你的项目使用到了prettier代码美化工具之后&#xff0c;使用ctrlaltL调整代码格式的时候会发现&#xff0c;代码没有被正确格式化&#xff0c;这是因为prettier代码美化工具没有设置格式化vue代码的设置。在下面中的run for files的括号里面加上vue即可 最后一步就是确保es…

【已解决】c++如何打印变量的类型

本博文源于笔者正在编写的c代码&#xff0c;在c/c中我们经常用auto去接一个变量&#xff0c;这样我们既可以不用知道变量或函数结果的类型&#xff0c;就可以轻松愉快编码&#xff0c;如果想要知道变量的类型呢&#xff1f;那就需要这样一个函数。 问题再现 想要用函数去打印…

【web】springboot3 生成本地文件 url

文章目录 流程效果静态资源访问ServiceServiceImplController 流程 avatar_dir&#xff1a;请求图片在服务端的存放路径user.dir&#xff1a;项目根目录 效果 静态资源访问 application.yml 设置静态文件存储路径custom:upload:avatar_dir: ${user.dir}/avatar_dir/avatar_d…

基于Java SSM框架实现在线作业管理系统项目【项目源码】

基于java的SSM框架实现在线作业管理系统演示 JSP技术 JSP技术本身是一种脚本语言&#xff0c;但它的功能是十分强大的&#xff0c;因为它可以使用所有的JAVA类。当它与JavaBeans 类进行结合时&#xff0c;它可以使显示逻辑和内容分开&#xff0c;这就极大的方便了运动员的需求…

2024年初会报名照片要求(必须白底哦)

24初级会计报名照片要求 近期彩色标准1寸、(白色背景)&#xff0c; jpg格式&#xff0c;大于10KB ,像素>295*413. 初级会计考试报名照片要求为本人近期正面、免冠、清晰完整的证件电子照。 初级会计报名照片应显示报考人员双肩、双耳、双眉&#xff0c;不得佩戴首饰&#xf…

基地动态|天府新区兴隆街道领导一行莅临天府锋巢直播产业基地考察交流

11月30日&#xff0c;天府新区兴隆街道党工委委员周杰、兴隆街道营商环境办主任章瑞芸、兴隆湖社区党委书记等领导一行莅临天府锋巢直播产业基地考察交流。天府锋巢直播产业基地运营团队、招商代表、入驻企业代表陪同参与。 考察中&#xff0c;基地运营团队向天府新区兴隆街道领…

打破硬件壁垒:TVM 助力 AI技术跨平台部署

文章目录 《TVM编译器原理与实践》编辑推荐内容简介作者简介目录前言/序言获取方式 随着人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;在全世界信息产业中的广泛应用&#xff0c;深度学习模型已经成为推动AI技术革命的关键。TensorFlow、PyTorch、MX…

codeblock如何使用

codeblock 使用的codeblock20.03版本&#xff0c;功能简介如下 settings&#xff0c; 全局设置compiler和debugger的配置 build option&#xff0c;项目右键配置项目编译属性 debugger,gdb调试路径不能包含中文或者空格 问题 不能调试的问题 编译代码-g参数输出调试符号重…

python tcp socket中实现SSL/TLS认证

SSL/TLS介绍 官话说SSL是安全套接层(secure sockets layer)&#xff0c;TLS是SSL的继任者&#xff0c;叫传输层安全(transport layer security)。 说白点&#xff0c;就是在明文的上层和TCP层之间加上一层加密&#xff0c;这样就保证上层信息传输的安全。如HTTP协议是明文传输…

get_reg_by_offset函数

get_reg_by_offset函数如下&#xff1a; 在建立了寄存器模型后&#xff0c;可以直接通过层次引用的方式访问寄存器&#xff1a; rm.invert.read(...); 但是出于某些原因&#xff0c;如果依然要使用地址来访问寄存器模型&#xff0c;那么此时可以使用get_reg_by_offset函数通过…

载誉前行!科士达新能源荣获光能杯卓越解决方案奖项

1月10日&#xff0c;由索比光伏网主办的“光能杯”光伏行业颁奖典礼在苏州隆重举行&#xff0c;科士达新能源凭借深厚的技术实力、强大的创新力、优质的产品及解决方案、丰富的项目经验等&#xff0c;斩获“卓越光储充一体化解决方案“殊荣。 作为智慧能源领域全场景解决方案供…

IDEA创建springboot+mybatis项目(java8 和java21可行)

IDEA创建springbootmybatis项目&#xff08;java8 和java21可行&#xff09; 今天博主讲一下&#xff0c;IDEA创建springbootmybatis项目的文章。 步骤分别是如下几步&#xff1a; 1. 创建maven项目 2. 配置pom.xml文件 3. 创建目录结构 4. 创建配置项目文件 5. 生成创建…

debug之pycharm调试:出现Collecting data......

pycharm调试时&#xff0c;出现Collecting data… 一直在这个界面很久&#xff0c;这是新版本的Pycharm的bug&#xff0c;通常在多线程的情况下发生。 解决方法&#xff1a; File->Setting->Build,Execution,Deployment->Python Debugger。把Gevent compatible勾选…