初识多线程编程
创始人
2024-04-17 07:12:44
0

在这里插入图片描述

文章目录

  • 一、线程
    • 线程与进程的区别
  • 二、多线程编程
    • Thread
    • 创建线程的方法

一、线程

我们开始引入进程,最主要的目的是去解决"并发编程"的问题,电脑进入了多核心,想要提高程序执行速度,就得将这些核心用起来。

我们在每次创建进程的时候都会为其分配空间和资源(速度十分的慢),不仅创建的时候慢,销毁,调度都很慢,这与我们并发编程的目的有所背离。

这时候就引入一个新的概念: 线程,线程也叫轻量级进程,在解决"并发编程"的前提下,让创建,销毁,调度的效率提高,至于为啥会提高,因为线程将创建时申请资源和销毁时释放资源给省下了。

线程与进程的区别

在这里举一个简单的例子,来感受一下: 现在有三个同学想要去教室学习。

第一种方案(多进程):

在这里插入图片描述

我们每个同学分别进了A,B,C教室,因为天很冷,都打开了空调。

第二种方案(多线程):

在这里插入图片描述

我们三个同学进入了同一间教室,打开了空调。

我们对比一下两种方案,第二种方案,资源成本开销要比第一种小很多,空调,桌子板凳都是可以公用一间的,这就是多线程的优势。

线程与进程之间的关系: 进程包含线程,一个进程可以只有一个线程,也可以有多个,但不能没有,只有第一个线程的开销是比较大的。同一个进程里的多个线程,共用了一份资源(内存,文件描述符表)

在这里插入图片描述

在操作系统中,线程是我们系统调用的基本单位,当我们谈到进程调度(当进程只有一个线程时)

线程是通过PCB来描述的,一个进程里的PCB可能是一个可能是多个,PCB里的状态,优先级,上下文,记账信息都是每个线程都是独一份,但是每次进程里的每个线程pid,内存指针,文件描述符表都是一样的。

**多线程与多进程比较: **

在这里插入图片描述

我们多进程的成本和资源开销比较大。

让学生更多,能否更好?

在这里插入图片描述

我们再增加线程时,也不可以一直提高效率,教室的桌子板凳是有限的(CPU核心数),学生太多,教师太吵闹,导致正在学习的同学,无法专心学习。

线程太多,核心数目有限时,不少的时间都浪费到量线程调度上面。

多线程的情况下,会发生线程安全问题。

在这里插入图片描述

当三个同学调节空调温度意见不统一时,就可以发生矛盾(线程不安全),在多进程中,就不会存在这种情况,各开各的,互不影响。

还有一种情况,要是一个教室两个同学放生矛盾,没有处理好,就会发生冲突,影响到整个教师的人。如果一个线程抛异常了,没有处理好,可能会把整个进程带走。

二、多线程编程

Thread

在我们java多线程编程中,最核心的类:Thread,因为这个类是java.lang底下的类,所以我们在使用的时候不需要自己导包。

在这里插入图片描述

class MyThread extends Thread{@Overridepublic void run() {System.out.println("MyThread!");}
}
public class Test {public static void main(String[] args) {Thread t = new MyThread();t.start();System.out.println("Main!");}
}    

我们来看一下我们第一个多线程代码,我来解释一下相关代码。

在这里插入图片描述

@Override表示我们重写父类Thread的run()方法,我们在创建线程对象时.用Thread接受子类对象时,调用run()方法执行的是子类的方法。

在这里插入图片描述

start()是我们线程当中很重要也很特殊的一个方法,当我们调用start()方法时,首先会调用操作系统的API去创建一个真正线程(PCB),并且把要执行指令交给PCB去执行,PCB被调度到CPU执行,执行run()方法。

在这里插入图片描述

我们这里有两个进程,一个是main进程,一个是t.start()创建出来的进程去执行run(),当run()执行完毕之后,该线程销毁。

还有需要注意:线程的执行顺序,并不是我们眼睛所表面看到的顺序,操作系统的调用线程是: 抢占式执行,那个线程先执行取决于操作系统调度器具体实现策略。我们可以通过JDK里所带的工具Jconsole查看我们Java当中的线程。

我们可以在jdk的bin目录下找。

在这里插入图片描述

也可以通过cmd命令访问.

在这里插入图片描述

在这里插入图片描述

我们通过后面的PID发现我们一共有三个进程,因为进程包含线程,我们想查看具体的线程就需要去进程里面查看。

我们发现第一个是jconsole,因为jconsole也是java也写。

第二个是IDEA。

第三个就是我们所运行的程序。

在这里插入图片描述

我们点进来,发现除了我们的main线程和Thread-0线程之外还有许多,这些线程都是JVM自带的。

创建线程的方法

1.继承Thread,重写run

class MyThread extends Thread{@Overridepublic void run() {System.out.println("MyThread!");}
}
public class Test {public static void main(String[] args) {Thread t = new MyThread();t.start();System.out.println("Main!");}
}    

2.实现Runnable接口

class MyRunnable implements Runnable{@Overridepublic void run() {System.out.println("Hello thread!");}
}
public class Test {public static void main(String[] args) {//去描述一下任务Runnable runnable = new MyRunnable();Thread t = new Thread(runnable);t.start();}
}    

3.使用匿名内部类,继承Thread

public static void main(String[] args) {Thread t = new Thread(){@Overridepublic void run() {System.out.println("MyThread!");}};t.start();}

创建了一个Thread的子类(未命名),所以才叫匿名内部类。

创建了子类的实例,让t指向。

4.使用匿名内部类,实现Runnable

public static void main(String[] args) {Thread t = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("MyThread!");}});t.start();
}

创建一个类,实现Runnable创建实列传给构造方法。

5.lambda表达式

public static void main(String[] args) {Thread t = new Thread(()->{System.out.println("MyThread!");});t.start();
}

相关内容

热门资讯

保存时出现了1个错误,导致这篇... 当保存文章时出现错误时,可以通过以下步骤解决问题:查看错误信息:查看错误提示信息可以帮助我们了解具体...
汇川伺服电机位置控制模式参数配... 1. 基本控制参数设置 1)设置位置控制模式   2)绝对值位置线性模...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
表格中数据未显示 当表格中的数据未显示时,可能是由于以下几个原因导致的:HTML代码问题:检查表格的HTML代码是否正...
本地主机上的图像未显示 问题描述:在本地主机上显示图像时,图像未能正常显示。解决方法:以下是一些可能的解决方法,具体取决于问...
表格列调整大小出现问题 问题描述:表格列调整大小出现问题,无法正常调整列宽。解决方法:检查表格的布局方式是否正确。确保表格使...
不一致的条件格式 要解决不一致的条件格式问题,可以按照以下步骤进行:确定条件格式的规则:首先,需要明确条件格式的规则是...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...