对线程和进程的理解

2023-05-16

进程和线程的区别

        进程:是指运行后的程序,是操作系统分配系统资源(内存空间、CPU)的最小单位。

        线程:每个进程由一个或者多个进程组成,线程是CPU进行分配和调度的最小单位。

        1.内存方面:

        进程需要的资源更多(堆、方法区、本地方法区),线程更轻量级(栈、程序计数器)。

        线程共享所在进程的内存空间(堆、方法区、本地方法区)。

        2.创建和销毁以及上下文切换:

        进程需要更多时间和资源,线程更快。

        3.相互通信方面:

        进程之间的通信比较麻烦(RPC、网络),线程之间通信更容易(通过进程共享的内存空间)。

     浅谈并行和并发

        一个CPU内核一个时间段只能运行一个线程的指令,因为CPU执行的速度特别快所以感觉多个程序同时运行 。

并发:一个CPU在多个线程间来回切换执行,不是真正同时执行。

并行:多个CPU同时执行多个线程,是真正同时执行。

多线程的作用和应用场景

线程是程序指令的单独的执行路径,多线程同时执行,大大提高了程序的执行效率。

应用场景:

        1.多线程下载

        2.游戏(图形绘制、游戏控制、网络通信。。)

        3.互联网应用(服务器为每个用户单独开线程,相互不影响)。

线程的三种实现方式

1.继承Thread

步骤:定义类继承Thread类,然后重写run方法,创建线程对象,调用start()方法。

/**
 * 使用Thread类实现自定义线程
 */
public class MyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i <100 ; i++) {
            System.out.println(Thread.currentThread().getName()+"-------"+i);
        }
    }


    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        //启动线程thread
        myThread.start();
        //主线程main
//        myThread.run();

        for (int i = 0; i <100 ; i++) {
            System.out.println(Thread.currentThread().getName()+"-------"+i);
        }
    }
}

疑问1: 执行run()和start()有什么区别?

调用run()方法是在主线程同步执行的,调用start后才会 启动新线程去执行。

疑问2:如果调用两次start会怎么样?

会抛出异常IllegalThreadStateException,线程是一次性的,不允许执行两次。

疑问3:多线程的执行顺序是怎么样?

多线程的执行是抢占式的,线程会去抢占CPU,抢到后执行自己的指令,执行过程中CPU可能被其它线程抢占,其它线程执行。

疑问4:上下文切换回原来的线程时,如何执行从哪里开始执行?

每个线程有自己的程序计数器,保存当前线程执行的行数,切换回来后继续执行下面的行代码。

2.实现Runnable接口

步骤:1.定义类实现Runnable接口,2.实现run方法,3.创建Thread对象,传入Runnable,调用start方法。

/**
 * 使用Runnable接口实现自定义线程
 */
public class MyRunable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i <100 ; i++) {
            System.out.println(Thread.currentThread().getName()+"-------"+i);
        }
    }

    public static void main(String[] args) {
        //创建MyRunable对象,创建Thread对象
        MyRunable myRunable = new MyRunable();
        Thread thread = new Thread(myRunable);
        thread.start();

        //匿名内部类写法
        Thread thread1 = new Thread(new Runnable(){
            @Override
            public void run() {
                for (int i = 0; i <100 ; i++) {
                    System.out.println(Thread.currentThread().getName()+"-------"+i);
                }
            }
        });
        thread1.start();
        //lambda表达式写法
        Thread thread2 = new Thread(()->{
            for (int i = 0; i <100 ; i++) {
                System.out.println(Thread.currentThread().getName()+"-------"+i);
            }
        });
        thread2.start();
    }
}

 疑问:继承Thread类和实现Runnable两种方式的区别?

解答:1.Java是单继承的,继承Thread类就不能继承其它类,实现接口没有此限制。

           2. 继承Thread不强制要求重写run,实现Runnable强制要求。

          3.Runnable可以使用Lambda表达式,语法简介。

          推荐使用Runnable方式。

3.实现Callable接口

 使用Thread类和Runnable类都是没有返回值的,如果想要有返回值,可以使用Callable。

步骤:1.实现Callable接口,重写call()方法,2.创建一个FutureTask对象传入Callable实现对象,3.创建Thread线程传入FutureTask对象,4.启动线程,5.通过FutureTask的get()方法获取返回值。

/**
 * 使用Callable接口自定义一个线程
 */
public class MyCallable implements Callable<Long> {
    @Override
    public Long call() throws Exception {
        long sum = 0;
        for (int i = 0; i <100000 ; i++) {
            sum += i;
        }
        return sum;
    }


    public static void main(String[] args) {
        //创建FutureTask对象,传入Callable对象
        FutureTask<Long> futureTask = new FutureTask<Long>(new MyCallable());
        //创建Thread对象,传入FutureTask对象
        Thread thread = new Thread(futureTask);
        //启动线程
        thread.start();
        try {
            //获取返回值
            Long value = futureTask.get();
            System.out.println(value);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

线程的生命周期

 线程常用的方法:

        start()         启动线程

        stop()         停止线程

        setName(String)       设置名字

        getName()                 获得名字

        sleep(long)                睡眠

        suspend()                 挂起线程

        resume()                  恢复线程

        yield()                       放弃执行

        join()                         合并线程

        setPriority(int)           设置线程优先级

        setDaemon(boolean) 设置后台线程

停止线程

       如果使用 stop() 调用stop会停止线程,不会释放锁,可能导致死锁,一般是禁用stop。

        停止线程的办法:1.等待run执行完。2. 在run执行代码中加入条件,中途停止执行。

线程的睡眠

Thread类的静态方法 sleep(毫秒数)

Thread.sleep(毫秒) 阻塞住当前线程,当时间结束后线程自动唤醒

疑问:wait和sleep的区别?

解答:1.调用对象不同: wait是锁对象调用,sleep是当前线程调用。

           2.唤醒机制不同: 线程进入wait后,要通过锁对象notify/notifyAll唤醒,sleep当时间结束自动唤醒。

           3.锁释放不同:线程进入wait后,会自动释放锁,线程sleep不会释放锁。

线程的优先级

线程有优先级从低到高分为1~10,默认是5,线程优先级越高抢到CPU的几率越高,可以给执行更重要任务的线程设置更高的优先级。

  Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                System.out.println(Thread.currentThread().getName() + "-->" + i);
            }
        });
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                System.out.println(Thread.currentThread().getName() + "-->" + i);
            }
        });
        //设置优先级
        thread2.setPriority(Thread.MAX_PRIORITY);
        thread1.setPriority(Thread.MIN_PRIORITY);
        thread1.start();
        thread2.start();

  后台线程

后台线程也叫守护线程(精灵线程),后台线程的任务是为其它线程提供服务,当其它线程都死亡后,后台线程会自动死亡。

使用:setDaemon(true) 设置后台线程

应用场景:gc线程(垃圾收集器)就是典型的后台线程。

/**
 * 守护线程
 */
public class DaemonDemo {
    public static void main(String[] args) {
        Thread daemon = new Thread(()->{
            for (int i = 0; ; i++) {
                System.out.println(Thread.currentThread().getName()+"-------"+i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        //设置守护线程
        daemon.setDaemon(true);
        daemon.setName("守护线程");
        daemon.start();
        //被守护线程
        for (int i = 0; i < 3 ; i++) {
            Thread thread =new Thread(()->{
                for (int j = 0; j < 10 ; j++) {
                    System.out.println(Thread.currentThread().getName()+"-------"+j);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
            thread.start();
        }
    }
}

合并线程

线程的执行是抢占式的,在线程内部可以合并其它线程,让其它线程的执行代码在当前线程前面执行,然后执行自己的指令。

/**
 * 合并线程
 */
public class JoinDemo {
    static Thread thread1=null,thread2=null;
    public static void main(String[] args) {
        thread1 = new Thread(()->{
            for (int i = 0; i <10; i++) {
                System.out.println(Thread.currentThread().getName()+"-------"+i);
                try {
                    //合并线程
//                    if(i==5){
//                        thread2.join();
//                    }
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread1.setName("合并线程1");
        thread1.start();

        thread2 = new Thread(()->{
            for (int i = 0; i <10; i++) {
                System.out.println(Thread.currentThread().getName()+"-------"+i);
                try {
                    if (i==5){
                        //合并线程
                        thread1.join();
                    }
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread2.setName("合并线程2");
        thread2.start();
    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对线程和进程的理解 的相关文章

  • Ubuntu 22.04LTS中使用aptitude来解决build-essential安装过程中过高版本包依赖问题

    小白近日安装完Ubuntu 22 04LTS后 xff0c 记不清是不是用了Software Updater还是自己手动upgrade了包 xff0c 导致在配置编译工具build essential 输入sudo apt install
  • 解决com.github.penggle kaptcha 2.3.2 报错

    需要从该地址处kaptcha的jar包下载位置 xff0c 从该地址下载jar包后 xff0c 可以把该jar包存放在C Users hp Desktop这个位置 xff0c 通过windows的cmd命令进入命令操作界面 执行以下命令 x
  • children 获取所有的子元素节点 2020/11/21

    children 获取所有的子元素节点 也是我们实际开发常用的 span class token operator lt span span class token operator span span class token consta
  • window常见事件 2020/11/24

    window onload是窗口 xff08 页面 xff09 加载时间 xff0c 当文档内容完全加载完成后触发该事件注意 xff1a window onload传统注册事件方式只能写一次 xff0c 如果有多个 xff0c 会以最后一个
  • 用if函数,进入无限循环,如何退出当前函数

    用if函数 xff0c 进入无限循环 xff0c 如何退出当前函数 wxml文件 span class token operator lt span view class span class token operator 61 span
  • form-type:submit和reset用法

    form type submit和reset用法 span class token operator lt span form bindsubmit span class token operator 61 span span class
  • checkbox背景颜色设置

    checkbox背景颜色设置 js文件 data span class token punctuation span languages span class token punctuation span span class token
  • MongoDB安装方案

    安装MongoDB 黑马头条项目 43 人力资源后台项目的接口服务均采用了 MongoDB 43 KOA2 技术栈 xff0c 所以在使用本地服务之前 xff0c 我们需要首先安装MongoDB xff0c 这也是该环节中出问题最多的一项
  • 小程序生成海报携带参数-云函数生成二维码

    1 逻辑代码 span class token keyword async span span class token function qcFn span span class token punctuation span span cl
  • 小程序动画

    小程序动画 点击事件 span class token comment lt 三大特色 gt span span class token tag span class token tag span class token punctuati
  • 小程序云开发--内容安全审查API云调用

    云调用 云调用是小程序 云开发提供的在云函数中调用微信开放接口的能力 xff0c 需要在云函数中通过 wx server sdk 使用 接口方法 openapi span class token punctuation span secur
  • 如何通过异或运算快速简单的实现两个数的值的交换

    实现代码如下图所示 xff1a public class class01 public static void swap int a int b a 61 a b b 61 a b a 61 a b System out println a
  • Cisco ISE AAA认证

    ISE 介绍 思科身份服务引擎 ISE 是一种身份验证安全服务 可以在简单而灵活的界面中显示用户和设备 查看并通过网络平台共享详细信息 使其了解用户 设备和网络的具体情况 当然Cisco还有类型的产品 xff0c 比如NAC ACS 那么三
  • PNET模拟器 安装(附下载地址)

    PNET模拟器介绍 Lab is Simple PNET安装步骤 1 将OVA文件导入Vmware 2 注意点 3 开机 xff0c 进行安装 4 选择第一个 5 安装成功 6 打开浏览器输入上边的IP地址 7 选择Online Mode
  • Python自动化备份网络设备配置

    前提 xff1a https blog csdn net weixin 50299079 article details 109300864 好嘞 xff0c 废话不多说 xff0c 开始搞 本文以Cisco CSR1000V设备配合Pyt
  • Check Point R80.40 防火墙

    Check Point 它是一家以色列的公司 xff0c 是面向全球企业用户业内领先的信息安全解决方案提供商 Check Point 解决方案对恶意软件 勒索软件和高级目标威胁的防范率处于业界领先水准 xff0c 可有效保护客户免受网络攻击
  • YangSuite 与 Netconf

    Cisco YangSuite 提供了一组工具和插件 xff0c 用于学习 xff0c 测试采用yang模型的可编程接口 xff0c 例如Netconf Restconf gNMI等 关于理论可以参考之前写的Cisco YangExplor
  • DMVPN 动态多点隧道技术

    DMVPN的特点 配置简单 中心站点只需要配置一次即可 xff0c 增加站点无需修改中心站点配置 xff0c 分支站点配置几乎相同 xff1b 性能好 能够实现动态mGRE隧道 xff0c 数据在分支之间能够直接通信 xff0c 一次加解密
  • Cisco Viptela SD-WAN 基本部署

    Cisco SD WAN Cisco SD WAN四平面 xff0c 四组件 管理平面 vManage xff1b 提供了一个高度可视化的仪表板 xff0c 可简化网络操作 它在整个 SD WAN 结构中提供集中配置 管理 操作和监控 编排
  • Ubuntu20.04安装ROS系统(其中里边出现了很多错误并解决了)

    目录 前言配置流程1 Software amp Update设置2 ifconfig命令3 安装支持SSH4 安装源5 密钥6 更新7 开始安装ROS8 配置环境变量9 验证是否安装成功 前言 首先非常感谢网上的各种安装教程 xff0c 以

随机推荐

  • 大龄程序员没有出路吗?

    点赞关注 xff0c 不会迷路 xff01 前言 说好的更新终于来了 文末有福利 关于这篇文章 xff0c 其实一直在犹豫怎么跟大家说 因为大龄程序员是一个群体 xff0c 但是每个人的情况又各有不同 这篇文章只能给你一个参考 xff0c
  • 怎么做一个分分钟哄女朋友开心的小程序

    点赞关注 xff0c 不会迷路 xff01 主要目的 xff1a 做一个以女朋友照片为背景的画布 xff0c 装饰点小花小草小气球小爱心 xff0c 另设一个女朋友的小图片可以自由的移动 那么就需要创建一个小花类一个气球类 xff0c 一个
  • maven中Profiles的配置及作用

    1 maven中Profiles的配置方法 xff1a pom xml xff1a pom xml中声明的profile只对当前项目有效 当你的项目存在父模块和字模块的时候 xff0c 通常配置在父模块即可 用户settings xml x
  • Java如果在try,catch里面执行return,那么还会不会执行finally?

    点赞关注 xff0c 不会迷路 xff01 总结 xff1a 1 不管有没有异常 xff0c finally中的代码都会执行 2 当try catch中有return时 xff0c finally中的代码依然会继续执行 3 finally是
  • 从三本院校到斩获字节跳动后端研发Offer

    文章篇幅较长 xff0c 都是满满的干货 xff0c 看完收获绝对很多 xff0c 文末有学习笔记和学习资料领取 前言 大家好 这次应博主的邀约 xff0c 写一篇关于我的 Java 自学经历 xff0c 希望对小伙伴们有所帮助 我本科就读
  • 【面试必看】肝出万字攻略,详解腾讯面试

    点赞关注 xff0c 不会迷路 xff01 2021最新学习面试资料 点击一起学习 暗号 xff1a csdn 最新学习资料 43 简历优化资源 前言 今天给大家分享下腾讯面试攻略 标题涉及的范围很广 xff0c 对多数面试腾讯的人而言 x
  • 国内最简单易用的源码,Nacos必须榜上有名!

    点赞关注 xff0c 不会迷路 xff01 2021最新学习面试资料 点击一起学习 暗号 xff1a csdn 最新学习资料 43 简历优化资源 最近新组件新的小组 xff0c 开始了新的项目 xff0c 项目的注册组件选择了我们国产的Na
  • 怎么做能防止B站再崩?

    点赞关注 xff0c 不会迷路 xff01 本文转载自 xff1a 敖丙 大家都知道虽然我是一个程序员 xff0c 但是我非常热爱运动 xff0c 比如跳舞 xff0c 这不每天回家睡前我都会在B站舞蹈区学习相关的舞蹈 昨天也不例外 xff
  • kali工具安装

    文章目录 汉化火狐浏览器 xff1a 安装google拼音输入法安装google浏览器安装beefssh安装gdebi安装 汉化火狐浏览器 xff1a 先执行命令 xff1a apt y install firefox esr l10n z
  • java多线程-8(CompletableFuture的简单使用)

    CompletableFuture简单使用 在JDK1 5引入的Future接口表示了一个异步计算返回的结果 但是使用Future获取异步返回结果的时候 xff0c 要么调用阻塞方法get 方法 要么轮询看isDone 是否为true ge
  • ROS导航小车2 AMCL(蒙特卡洛)粒子滤波定位算法(仅作个人记录)

    AMCL原理概念 AMCL adaptive Monte Carlo Localization 自适应蒙特卡洛定位 xff0c A也可以理解为augmented xff0c 是机器人在二维移动过程中概率定位系统 xff0c 采用粒子滤波器来
  • Linux安装docker-compose时使用github.com拒接连接处理

    报错如 xff1a Failed to connect to raw githubusercontent com port 443 Connection refused 主要问题就是拒接服务到github com xff0c 你可以测试pi
  • ESP32-CAM 在 Web 服务器中拍照和显示

    ESP32 CAM 在 Web 服务器中拍照和显示 项目简介所需部件项目概况 安装 ESP32 附加组件安装库安装 ESPAsyncWebServer 库安装 ESP32 的异步 TCP 库 ESP32 CAM 拍摄和显示照片 Web 服务
  • Linux系统常用命令总结

    目录 基本常用命令 xff1a 关机重启命令 xff1a 防火墙相关命令 xff1a 针对于CentOS7系统 重定向和追加 xff1a 打包压缩命令 xff1a vi vim编辑器 xff1a 软件包安装命令 xff1a 文件权限设置 x
  • ROS入门级教程

    目录 前言 一 ROS简介与安装 二 ROS文件系统 三 ROS核心概念 1 节点 2 话题 3 通讯机制 四 ROS的编译与简单使用 五 调试工具 1 Rviz和Gazebo 2 rqt工具 3 rosbag 六 常用指令 1 常用的文件
  • Springboot 框架

    SpringBoot 1 用来简化 spring 初始搭建和开发过程使用特定的方式进行配置 properties 或者 yml 文 件 2 创建独立的 spring 引用程序 main 方法运行 3 嵌入 Tomcat 无需部署 war 包
  • 新建github分支

    新建github分支 xff0c 可以 直接在github仓库上创建 或者 通过git命令创建 这里以 在main分支下创建test分支 为例 方法一 xff1a 直接在github仓库上创建分支 1 进入相应的仓库 xff0c 点击 Sw
  • Linux应用层开发(文件、多线程,多进程、进程间通信)

    文件IO编程 linux 下 切皆 件 xff0c 我们操作外设 标 键盘 磁盘等外设 就像操作 件 样 要如何操作 件与外设 xff0c 就必须熟练掌握 件IO input 写 output读 1 多文件编程 多 件编程 xff1a 把
  • VINS-MONO运行TUM VIO数据集真实轨迹问题处理

    小loser第一次写记录 xff0c 再次记录一下测试TUM VIO数据集碰到的问题及处理 VINS本身输出的数据需要进行格式转换才能用 xff0c 输出文件修改参考这个博客 Ubuntu 18 04 VINS Mono运行与EVO的评测与
  • 对线程和进程的理解

    进程和线程的区别 进程 xff1a 是指运行后的程序 xff0c 是操作系统分配系统资源 xff08 内存空间 CPU xff09 的最小单位 线程 xff1a 每个进程由一个或者多个进程组成 xff0c 线程是CPU进行分配和调度的最小单