认识线程和创建线程

news2025/1/24 14:05:09

目录

1.认识多线程

1.1线程的概念

1.2进程和线程

1.2.1进程和线程用图描述关系

 1.2.2进程和线程的区别

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

 2.创建线程

2.1继承 Thread 类

 2.2实现 Runnable 接口

 2.3匿名内部类创建 Thread 子类对象

2.4匿名内部类创建 Runnable 子类对象

2.5lambda 表达式创建 Runnable 子类对象 


1.认识多线程

1.1线程的概念

引入线程:进程虽然可以很好的实现并发编程,但在进行频繁的进程创建和销毁的过程中开销比较大(体现在资源的申请和释放上)。所以就发明了比进程更轻量的线程。

线程与进程相比:

(1)创建线程比创建进程更快 .
(2)销毁线程比销毁进程更快 .
(3)调度线程比调度进程更快 .
线程具体是什么?
  一个线程就是一个 " 执行流 ". 每个线程之间都可以按照顺讯执行自己的代码 . 多个线程之间 " 同时 " 执行 着多份代码.

1.2进程和线程

1.2.1进程和线程用图描述关系
1.进程是包含线程的 . 每个进程至少有一个线程存在,即主线程。
2.进程和进程之间不共享内存空间 . 同一个进程的线程之间共享同一个内存空间 .
 1.2.2进程和线程的区别

(高频面试题)

1.进程是包含线程的。

2.每个线程就是一个 独立的"执行流",可以单独执行一些代码,并参与到CPU的调度(状态,上下文,优先级,记账信息,每个线程都有自己的一份)

3.每个进程都有自己的资源,进程中的线程共用一份资源(内存空间和文件描述符表)

(2)与(3)说明:

进程是系统分配资源的最小单位,线程是系统调度的最小单位。

4.进程与进程之间不会相会影响,但 线程与线程之间会相会影响。如果一个进程中的某个线程抛出异常,可能会导致进程中的所有线程都异常终止。

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

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

注意:

(1)线程与线程之间可能会相互干扰,产生逻辑bug,引起线程安全。

(2)线程不是越多越好,线程太多调度开销可能会非常明显。


 

 2.创建线程

2.1继承 Thread

(1)继承 Thread 来创建一个线程类

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

此处 run()不需要手动调动,在线程创建好之后JVM会自动调用执行(回调函数)。

(2)创建 MyThread 类的实例

MyThread t = new MyThread();

创建出的实例才是真线程。 

 (3)调用 start 方法启动线程 

t.start(); // 线程开始运行

此时才会真正调用系统API,在系统内核中创建出线程(执行run())。

 为啥要在系统内核中创建出线程?

因为程序有时需要对软硬件资源进行操作。

完整示例:

public class ThreadDemo1 {
    public static void main(String[] args) {
        Thread t = new MyThread();
        t.start();
        while(true){
            System.out.println("main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

class MyThread extends Thread{
    @Override
    public void run() {
        while(true){
            System.out.println("MyThread");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

 进程创建第一个线程时开销最大,之后的线程开销都比较小,但不是0,main线程其实是第一个线程。

 

一直循环…… 

 当有多个线程,它们的执行顺序是不确定的。


 使用 jconsole 命令观察线程

我们可以使用jdk自带的工具 jconsole查看当前Java进程中所有的线程

第一步,找到jdk

第二步,点进去,找到里面的bin文件点进去

第三步,在bin文件夹里搜索jconsole 

第四步,找到你所创建进程点击线程进行查看

 


 2.2实现 Runnable 接口

(1) 实现 Runnable 接口

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

2) 创建 Thread 类实例, 调用 Thread 的构造方法时将 Runnable 对象作为 参数.

Thread t = new Thread(new MyRunnable());

(3) 调用 start 方法

t.start(); // 线程开始运行 

 完整示例:

public class ThreadDemo2 {
    public static void main(String[] args) {
        Thread t = new Thread(new MyRunnable());
        t.start();
        while(true){
            System.out.println("main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

class MyRunnable implements Runnable{

    @Override
    public void run() {
        while(true){
            System.out.println("MyRunnable");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
这种写法其实就是把线程和要执行的任务进行了解耦合。
对比上面两种方法 :
1.继承 Thread , 直接使用 this 就表示当前线程对象的引用 .
2.实现 Runnable 接口 , this 表示的是 MyRunnable 的引用 . 需要使用 Thread.currentThread()

 2.3匿名内部类创建 Thread 子类对象

// 使用匿名类创建 Thread 子类对象
Thread t1 = new Thread () {
    @Override
    public void run () {
        System . out . println ( " 使用匿名类创建 Thread 子类对象 " );
  }
};

  完整示例:

public class ThreadDemo3 {
    public static void main(String[] args) {
        Thread t=new Thread(){
            @Override
            public void run() {
                while (true){
                    System.out.println("使用匿名类创建 Thread 子类对象");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };
        t.start();
        while(true){
            System.out.println("main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

2.4匿名内部类创建 Runnable 子类对象

// 使用匿名类创建 Runnable 子类对象
Thread t2 = new Thread ( new Runnable () {
    @Override
    public void run () {
        System . out . println ( " 使用匿名类创建 Runnable 子类对象 " );
  }
});

  完整示例:

public class ThreadDemo4 {
    public static void main(String[] args) {
        Thread t=new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    System.out.println("使用匿名类创建Runnable子类对象");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        });
        t.start();
        while(true){
            System.out.println("main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

2.5lambda 表达式创建 Runnable 子类对象 

 lambda就是让方法看上去脱离类,单独存在。

// 使用 lambda 表达式创建 Runnable 子类对象
Thread t3 = new Thread (() -> System . out . println ( " 使用匿名类创建 Thread 子类对象 " ));
Thread t4 = new Thread (() -> {
    System . out . println ( " 使用匿名类创建 Thread 子类对象 " );
});

  完整示例:

  public static void main(String[] args) {
        Thread t=new Thread(() -> {
            while(true){
                System.out.println("使用匿名类创建Runnable子类对象");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        t.start();
        while(true){
            System.out.println("main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

都看到这了,不如关注一下,给个免费的赞 

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

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

相关文章

LLM之Agent(五)| AgentTuning:清华大学与智谱AI提出AgentTuning提高大语言模型Agent能力

​论文地址:https://arxiv.org/pdf/2310.12823.pdf Github地址:https://github.com/THUDM/AgentTuning 在ChatGPT带来了大模型的蓬勃发展,开源LLM层出不穷,虽然这些开源的LLM在各自任务中表现出色,但是在真实环境下作…

1.cloud-微服务架构编码构建

1.微服务cloud整体聚合父工程 1.1 New Project 1.2 Maven选版本 1.3 字符编码 1.4 注解生效激活 主要为lombok中的Data 1.5 java编译版本选8 1.6 File Type过滤 *.hprof;*.idea;*.iml;*.pyc;*.pyo;*.rbc;*.yarb;*~;.DS_Store;.git;.hg;.svn;CVS;__pycache__;_svn;vssver.scc;v…

嵌入式C语言代码的基本编写规范要求

编码规范,没有最好,只有最合适,有但不执行不如没有。1 编码原则 1.1 可读性原则 (1)清晰第一 清晰性是易于维护程序必须具备的特征。维护期变更代码的成本远远大于开发期,编写程序应该以人为本&#xff0c…

vue3中子组件调用父组件的方法

<script lang"ts" setup>前提 父组件&#xff1a; 子组件&#xff1a; const emit defineEmits([closeson]) 在子组件的方法中使用&#xff1a; emit(closeson)

Spring Boot学习随笔- 集成JSP模板(配置视图解析器)、整合Mybatis(@MapperScan注解的使用)

学习视频&#xff1a;【编程不良人】2021年SpringBoot最新最全教程 第五章、JSP模板集成 5.1 引入JSP依赖 <!--引入jsp解析依赖--> <!--C标签库--> <dependency><groupId>jstl</groupId><artifactId>jstl</artifactId><version&…

ES6之Symbol

ES6中为我们新增了一个原始数据类型Symbol&#xff0c;让我为大家介绍一下吧&#xff01; Symbol它表示是独一无二的值 Symbol要如何创建 第一种创建方式&#xff1a; let sy Symbol()第二种创建方式&#xff1a; let sy Symbol.for()具体独一无二在哪呢&#xff1f;它们的地…

【MyBatis系列】MyBatis字符串问题

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Java中的IO流①——IO流的体系、字节流、try...catch异常处理

概述 IO流的分类 IO流的体系 这四个类都是抽象类&#xff0c;所以需要实现类对象才能使用---> 字节流 FileInputStream--> 书写细节 代码示范 此时文件a.txt内容为abcde 使用char强转和read方法调用五次read方法--> public static void main(String[] args) throws IO…

JavaScript-节点操作

节点操作 DOM节点 DOM节点&#xff1a;DOM树里每一个内容都称之为节点 节点类型&#xff1a; 元素节点 所有的标签 比如body、divhtml时跟节点 属性节点 所有的属性&#xff0c;比如href 文本节点 所有的文本 其他 查找节点 节点的关系&#xff1a;针对的找亲戚返回的都是…

redis中缓存雪崩,缓存穿透,缓存击穿等

缓存雪崩 由于原有缓存失效&#xff08;或者数据未加载到缓存中&#xff09;&#xff0c;新缓存未到期间&#xff08;缓存正常从Redis中获取&#xff0c;如下图&#xff09;所有原本应该访问缓存的请求都去查询数据库了&#xff0c;而对数据库CPU和内存造成巨大压力&#xff0c…

H264视频编码原理

说到视频&#xff0c;我们首先想到的可能就是占内存。我们知道一个视频是由一连串图像序列组成的&#xff0c;视频中图像一般是 YUV 格式。假设有一个电影视频&#xff0c;分辨率是 1080P&#xff0c;帧率是 25fps&#xff0c;并且时长是 2 小时&#xff0c;如果不做视频压缩的…

每日一练【三数之和】

一、题目描述 15. 三数之和 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请 你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可…

【Java】构建哈夫曼树和输出哈夫曼编码

问题背景 一个单位有12个部门&#xff0c;每个部门都有一部电话&#xff0c;但是整个单位只有一根外线&#xff0c;当有电话打过来的时候&#xff0c;由转接员转到内线电话&#xff0c;已知各部门使用外线电话的频率为&#xff08;次/天&#xff09;&#xff1a;5 20 10 12 8 …

算法Day23 简单吃饭(0-1背包)

简单吃饭&#xff08;0-1背包&#xff09; Description Input Output Sample 代码 import java.util.Scanner; public class Main {public static void main(String[] args) {Scanner scanner new Scanner(System.in);int n scanner.nextInt();int total scanner.nextInt(…

Java一对一聊天程序

我们首先要完成服务端&#xff0c;不然出错&#xff0c;运行也要先运行服务端&#xff0c;如果不先连接服务端&#xff0c;就不监听&#xff0c;那客户端不知道连接谁 服务端 import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.Actio…

Qt之QSlider和QProgressBar

Qt之QSlider和QProgressBar 实验结果 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget) {ui->setupUi(this);connect(ui->dial,&QDial::valueChanged,this,&Widget::do_val…

Redis rdb源码解析

前置学习&#xff1a;Redis server启动源码-CSDN博客 1、触发时机 1、执行save命令--->rdbSave函数 2、执行bgsave命令--->rdbSaveBackground函数或者&#xff08;serverCron->prepareForShutdown&#xff09; 3&#xff0c;主从复制-->startBgsaveForReplication…

序列的Z变换(信号的频域分析)

1. 关于Z变换 2. 等比级数求和 3. 特殊序列的Z变换 4. 因果序列/系统收敛域的特点 5. 例题

C/C++,树算法——二叉树的插入、移除、合并及遍历算法之源代码

1 文本格式 #include<iostream>; using namespace std; // A BTree node class BTreeNode { int* keys; // An array of keys int t; // Minimum degree (defines the range for number of keys) BTreeNode** C; // An array of child pointers …

Redis 命令全解析之 Hash类型

文章目录 ⛄介绍⛄命令⛄RedisTemplate API⛄应用场景 ⛄介绍 Hash类型&#xff0c;也叫散列&#xff0c;其value是一个无序字典&#xff0c;类似于Java中的 HashMap 结构。 String结构是将对象序列化为JSON字符串后存储&#xff0c;当需要修改对象某个字段时很不方便&#xf…