当前位置: 首页 > news >正文

JavaEE初阶——多线程(1)初识线程与创建线程

目录

一、进程

1.1 什么是进程

1.2 PCB(进程控制块)

1.3 进程的组织方式

二、线程

2.1 认识线程

2.1.1 线程是什么

2.1.2 为什么要有线程

2.1.3 进程和线程的区别

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

2.2 创建线程

2.2.1 第一个线程对象

2.2.2 创建两个线程同时运行

2.2.3 使用jconsole观察线程的状态

2.3 创建线程的方法

2.3.1 继承Thread类

2.3.2 实现Runnable接口

2.3.3 其他变形

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

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

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


一、进程

1.1 什么是进程

在学习线程之前,我们先来了解一下进程。我们的计算机都会有操作系统,他对下(硬件)管理各种计算机设备,对上(软件)为各种软件提供一个稳定的运行环境。那么进程其实是操作系统对一个正在运行的程序的一种抽象,换言之,我们可以把进程看作程序的一次运行过程,也就是运行的程序在操作系统以进程的形式存在。

1.2 PCB(进程控制块)

我们知道在Java语言中,我们通过类来描述一个特征,这个类就是PCB:进程控制块,我们来了解一下这个类中有什么属性

class PCB{PID //PID ———— 进程的唯一标识内存指针 //程序在运行之前操作系统会为它分配一片有效空间,内存指针指向这片空间文件描述符表(集合)//程序运行起来后需要访问一些文件资源,操作系统负责位程序分配这些资源进程的状态 //描述当前进程的运行状态:就绪,堵塞……进程的优先级进程的上下文 //保存上下文(读档),恢复上下文(存档)进程的统计信息 //统计进程在CPU上的运行时间和次数
}

这段代码只是伪代码,不能真的运行,只是用来描述PCB里面的内容。这样一个PCB对象,就代表一个实实在在运行着的程序,也就是进程

根据了解PCB之后我们就知道每创建一个PCB后,系统就会集中分配很多空间和资源。

进程是系统分配资源的最小单位

1.3 进程的组织方式

我们通过一个双向链表来组织PCB

  • 创建一个进程就是把PCB加入到链表中
  • 销毁一个进程就是把PCB从链表中删除
  • 查看所有进程就是遍历双向链表

二、线程

2.1 认识线程

2.1.1 线程是什么

一个线程就是一个执行流,每个线程都可以按照顺序执行自己的代码,多个线程之前是可以同时执行多份代码。

2.1.2 为什么要有线程

我们之前提到了进程是一个运行的程序,申请了很多空间和资源。如果有新的代码要运行,再创建一个进程不就行了,为什么要去引入线程呢?

多进程确实可以利用CPU资源去处理复杂业务,可以提高业务的处理效率。但是我们再去回想一个进程的创建需要什么,每创建一个进程,我们就需要分配资源分配空间,销毁进程又需要释放这些资源,而这些操作对系统的性能影响是比较大的。

有时候我们处理一件事情,申请一份资源就够了,就算有新的任务下达,我们也使用刚刚的资源就好了,不要再另外申请,所以我们引入了线程的概念。

线程共用进程启动时申请的资源,线程也可以叫做轻量级的进程。我们现在用图来更好的理解一下

我们现在假设张三要开设工厂

  • 1.申请一片地皮
  • 2.建厂
  • 3.建生产线
  • 4.招人,买材料
  • 5.开工生产

我们把他开设工厂的步骤简单分为上面五步,很明显开设工厂是花费了很多钱申请了很多资源(地皮,建厂),现在厂里只有一条生产线。那现在生产线1已经不够处理订单的需求了,我们要新建生产线2,我们此时是重新建一个厂,再申请资源,还是在原来的厂里新建一个生产线?

很明显我们没必要再建一个厂,直接新建一个生产线2即可。两个生产线都是共用了这个厂的资源,新建生产线也比新建一个厂要效率高的多。

工业园操作系统
张三的工厂一个进程
生产线一个线程
开工生产开始线程的任务

相信我们现在可以理解,为什么要引入线程了,线程不需要申请资源浪费时间,可以提高效率

我们可以从任务管理器的CPU性能看到图片中的信息,图片中显示逻辑处理器为20,这个数字决定了创建线程的个数

我们现在假设一个场景,有一个任务是需要吃100只鸡,那如果只有一个人也就是一个线程去吃效率肯定是比较低的,那我们可以喊多几个人来吃也就是多创建几个线程来完成这个任务,这样效率肯定会提高。

那我喊十个人来吃鸡,和喊一百个人来吃鸡,这两种情况也就对应着10个线程完成一个任务和100个线程来完成一个任务到底谁的效率会更高。

此时其实是10个线程效率会更高,因为我们这个CPU显示有20个逻辑处理器,当我们申请的线程个数大于这个数,会有很多线程出现堵塞的情况,反而会造成拥堵,浪费资源,降低效率。

  • 当线程数小于逻辑处理器数时,效率会提升
  • 当线程数大于逻辑处理器数是,由于过多的线程在阻塞等待状态,并没有真正发挥并行的效果, 反而因为创建线程消耗了系统资源

2.1.3 进程和线程的区别

进程是包含线程的,每个进程至少有一个线程存在,即主线程

进程和进程直接是不共享内存空间的,同一个进程的线程之间是共享同一个内存空间

还是用我们刚刚建厂的例子,张三和李四的工厂不是用的同一个空间和资源,也就是两个进程不共享内存空间,但是张三的生产线都是在张三的厂里,也就是一个进程的线程共享空间

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

一个进程崩溃一般不会影响到其他进程,一个线程崩溃往往可能影响同进程的其他线程一起崩溃

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

线程是操作系统中的概念,操作系统内核实现了线程这样的机制,并且对用户层提供了一些API工用户使用

Java标准库中的额Thread类可以是做是对操作系统提供的API进行了进一步的抽象和封装

2.2 创建线程

2.2.1 第一个线程对象

class Mythread1 extends Thread{@Overridepublic void run() {while(true){System.out.println("hello my thread...");}}
}

Mythread1是我们自定义的一个线程类,这个类需要集成Java中的Thread类,在这个类中我们可以重写run方法,在run方法中我们可以自定义任务,只要在run方法中写我们的代码逻辑即可。

public class Demo1 {public static void main(String[] args) {Mythread1 mythread1=new Mythread1();mythread1.start();}
}

定义好我们的线程类后,我们可以实例化一个对象,调用start方法,即可开始运行线程

我们可以去查看start方法的源码,发现他其实是调用了本地方法(native)

这里我们重点区分两个概念

  • 操作系统中的线程PCB
  • Java中的线程,Thread类的一个对象,是对PCB的一个抽象

所以PCB和Thread类不是一个概念

线程启动的过程是

Java中创建一个线程对象——>start方法被调用——>启动线程——>JVM调用系统的API——>申请操作系统的PCB——>CPU调度执行

2.2.2 创建两个线程同时运行

class Mythread1 extends Thread{@Overridepublic void run() {while(true){try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("hello my thread...");}}
}
public static void main(String[] args) {Mythread1 mythread1=new Mythread1();mythread1.start();//Mythread1线程//主线程while(true){try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("hello main thread");}
}

为了方便观察现象,我们调用了Thread类中的sleep方法,让线程休眠1秒再进行

我们可以看到,我们自定义的线程是一个死循环,我们main方法中的主线程也是一个死循环,如果按照我们以前的单线程想法,程序应该会在mythread1的run方法死循环打印,但是我们观察下面的运行结果,可以看到主线程和自定义线程是在同时进行的,互不打扰。

同时不要认为他是按照顺序进行,线程的执行顺序并没有什么规律,我们能看到图中红色区域,有可能先打印mythread1的内容,有可能先打印主线程的内容,这是因为CPU是抢占式调度线程,这是随机不确定的,所以我们能观察的不同的执行顺序。

2.2.3 使用jconsole观察线程的状态

jconsole在jdk-版本号(jdk-17)\bin目录下

我们选择Demo1进程

这里的Thread-0就是线程在操作系统里的名字,这是默认的线程名Thread-N,N从0开始

main就是主线程

2.3 创建线程的方法

2.3.1 继承Thread类

我们刚刚创建线程使用的是下面的代码

class Mythread1 extends Thread{@Overridepublic void run() {while(true){System.out.println("hello my thread...");}}
}

这样创建线程的方法就是自定义一个线程类继承Thread类

2.3.2 实现Runnable接口

class MyRunnable implements Runnable{@Overridepublic void run() {while(true){try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("实现Runnable接口...");}}
}

我们创建一个MyRunnable类实现Runnable接口

    public static void main(String[] args) {Thread t=new Thread(new MyRunnable());t.start();}

通过Thread类调用构造方法是将MyRunnable对象作为参数传入,再调用start方法,显示正常运行

通过实现Runnable接口这样的方法,可以单独定义线程的任务,我们是推荐这样的做法的。因为这样可以让线程类和我们的业务解耦,让代码尽量分离,以便后面修改代码让互相的影响最小化,如果任务有变动,只需要修改一份代码即可。我们需要什么任务就传入对应的Runnable对象即可

2.3.3 其他变形

2.3.3.1 匿名内部类创建Thread子类对象
    public static void main(String[] args) {Thread t1=new Thread(){@Overridepublic void run() {System.out.println("匿名内部类实现Thread子类...");}};t1.start();}
2.3.3.2 匿名内部类创建Runnable子类对象
    public static void main(String[] args) {Thread t1=new Thread(new Runnable() {@Overridepublic void run() {System.out.println("匿名内部类实现Runnable子类");}});t1.start();}
2.3.3.3 lambda表达式创建Runnable子类对象

我们来看一下Runnable接口的源代码,我们可以发现这个接口中只有一个方法。

那么像这种只有一个方法的接口,我们称为函数式接口。对于函数式接口,我们可以使用lambda表达式来简化

    public static void main(String[] args) {Thread t1=new Thread(()->{System.out.println("lambda表达式实现Runnable子类");});t1.start();}
http://www.dtcms.com/a/475449.html

相关文章:

  • jsp电子商务网站建设源码商业网站建设规划范文
  • webrtc弱网-BitrateEstimator类源码分析与算法原理
  • 卫辉市住房和城市建设局网站建设网站商城后台系统
  • 网站建设合同报价做网站店铺装修的软件
  • RND1:目前最强的扩散LLM
  • 企业推广建站汕头最好的seo外包
  • 网站历史记录怎么恢复团风做网站
  • 《从HelloWorld到微服务架构Java编程的进化之路》
  • 有那个网站可以做报名链接的聊城网架公司
  • 学Java第三十六天--------内部类
  • 开源php建站系统沙井建网站
  • 温州网站建设对比网站系统开发怎么做
  • 专门做旅游攻略的网站有哪些团购火锅自助网站建设
  • 临沂网站开发技术员广州引流推广公司
  • 承包酒席可以做网站吗廊坊百度关键词推广
  • 风景区网站代码有人做几个蝎子养殖门户网站
  • 毕业设计做网站有什么好处网站后台英文
  • php网站标题修改网站建设需要的技术人员
  • 【大数据开发实践】Kafka REST Proxy~无缝集成 Kafka
  • 做网站欢迎页什么意思阿里云搜索引擎
  • 广东真空共晶炉公司
  • wordpress网站发布文章做网站的创始人
  • 上海市建设考核中心网站无锡企业网站
  • 【计算机组成原理】第五章:中央处理器
  • ICT 数字测试原理 20 - -VCL中预处理的过程
  • 房地产网站建设的目的淘宝客网站怎么做推广计划
  • 江西网站设计哪家强ai绘画软件免费
  • 公司网站首页的图片怎么做电脑网页尺寸一般是多少
  • 企业网站 数据库设计网站开发老板排名
  • 开放平台直播优化课程体系