JavaEE初阶——多线程(一)

在这里插入图片描述

T04BF

👋专栏: 算法|JAVA|MySQL|C语言

🫵 小比特 大梦想

此篇文章与大家分享多线程的第一部分:引入线程以及创建多线程的几种方式
此文章是建立在前一篇文章进程的基础上的
如果有不足的或者错误的请您指出!

1.认识线程

我们知道现代的cpu大多都是多核心的cpu,此时通过特定的编程技巧,即可以将不同的进程调度到多个cpu上执行,也就是我们在进程章节里面讲到的"并发".在我们的日常开发中,往往一个服务器要同时面对多个客户端,为多个客户端提供服务,此时如果只利用一个cpu处理客户端的请求,那么响应速度就会变慢.那么此时"多核心"的cpu就能起到一定的效果,每一个客户端连上服务器的时候,服务器都创建一个进程给客户端提供服务,客户端断开了,服务器就把进程销毁
但是随之而来的又是一个问题,服务器频繁的创建,销毁进程实际上也会对服务器的响应速度造成影响
我们引入多线程的初心就是为了解决上述"进程太重"的问题,线程实际上也称为"轻量级进程",顾名思义,他的创建和销毁开销都比进程要小
线程可以当成是进程的一部分,一个线程中可能含有一个线程,也可能含有多个线程
我们在进程章节谈到的进程,就是只针对一个进程里面只有一个线程而言的
我们在前面说过,描述一个进程是使用pcb这样的结构体,但是实际上准确来说应该是:一个pcb描述的是一个线程,多个pcb共同描述一个进程
那么我们对pcb中有些属性就该有新的认识
(1)pid :实际上一个线程对应的是一个pid,因此不同线程的pid是不一样的
(2)内存指针和文件描述操作符:在若干个线程中,这两个属性实际上是一样的
(3)状态、上下文、优先级、记账信息对应的是每个线程自己的属性
(4)tgid:在一个进程内是一样的,不同进程就不一样
此时,在同一个进程内,若干个线程之间的资源(内存资源和文件资源)是共享的,但是每个线程又是独立地在cpu上调度执行

因此就有一个重要的结论:进程是系统进行资源分配的基本单位,线程是系统调度执行的基本单位
(在进程章节谈到的进程调度,实际上就是线程调度)

为什么说线程比进程更轻量级??为什么说线程的创建和销毁比进程开销更小??

本质上就是因为创建进程的时候就要涉及到资源的分配,销毁进程的时候涉及到资源的销毁,而创建线程,由于同一个线程之间的资源是共享的,相当于资源已经有了,就省去了分配资源 / 销毁资源的步骤,只是在创建第一个线程(也就是创建进程的时候)需要这个步骤,因此线程自然就轻量

但是多线程就没有缺点嘛??

首先,一个进程内的线程不能无限地引入,引入的线程一旦多了,单位时间内要进行调度的次数也就增多了,此时对加大线程调度的开销,当这种开销太大的时候,实际上性能可能不升反降

其次,当多个线程同时访问和操作某写共享资源时,如多个线程并发地读取、修改、写入共享数据时,如果没有适当的同步措施,就可能会引发数据竞争等一系列的问题,就会让程序出现bug,这就是我们后面要谈到的线程安全问题

再者,如果一个线程出现问题,就可能会影响到其他线程,如某个线程如果抛出异常,但是没有很好地处理异常,就会使整个进程退退出

2.第一个多线程代码

2.1通过继承Thread来创建一个线程类

class MyThread extends Thread{@Overridepublic void run(){while(true){System.out.println("hello world");}}
}
public class Demo1 {public static void main(String[] args) {Thread t = new MyThread();thread.start();while(true){System.out.println("main");}}
}

(1)在MyThread中的run方法,就是用来描述这个线程具体要干什么活
(2)在上述代码中,实际上存在着两个线程,一个是我们main线程(也称主线程),一个是t线程,此时main线程和t线程就在并发式的执行了
我们可以通过java提供的工具:jconsole来清楚地看到不同的进程
在这里插入图片描述
在这里插入图片描述
至于剩下的线程,就是Jvm帮我们做的一些其他的工作,例如垃圾回收等
(5)可以利用sleep让线程进入阻塞状态
实际上就是让当前线程主动放弃去cpu上执行,时间到了线程才会解除阻塞状态,重新有机会被调度到cpu上执行

class MyThread extends Thread{@Overridepublic void run(){while(true){System.out.println("hello world");try {Thread.sleep(1000);//谁调用,谁就sleep} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}
public class Demo1 {public static void main(String[] args) throws InterruptedException {Thread thread = new MyThread();thread.start();while(true){System.out.println("main");Thread.sleep(1000);}}
}

此时运行后可以明显发现打印速度变慢了
(6)在上面代码中,某一时刻先打印main还是Thread是不确定的,这是因为多个线程之间的调度顺序是"无序"的,在操作系统内部也称为抢占式执行.即任何一个线程在执行到任何一段代码的时候,都会被其他线程抢占了他的cpu资源,就会给别的线程执行,就会充满"随机性".也正是因为这样的随机性,导致我们很多程序的执行结果是"不可预估的",甚至可能带来bug
(7)关于start
我们前面说到到run方法,只是描述了一个线程具体应该干什么,而start方法才是操作系统提供的"创建线程"的api,此时调用start方法,在内核中才会真正创建一个pcb,真正为这个线程分配资源,进一步系统调度到这个线程的时候,才会执行到run方法
而如果我们直接执行run方法,那么就只是简单的执行run方法里面的代码逻辑,并没有创建一个线程

像这样创建一个方法(run),不去手动调用,而是交给系统 / 其他的库 / 其他的框架调用,就是回调函数

3.2通过实现runnable接口创建线程

class MyRunnable implements Runnable {@Overridepublic void run(){while(true){System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}
public class Demo2 {public static void main(String[] args) throws InterruptedException {Thread t = new Thread(new MyRunnable());t.start();System.out.println("hello main");}
}

Runnable的作用就只是描述了一个任务,这个任务与具体的执行机制无关,也就是我们是通过线程的方式执行还是通过其他的方式执行无所谓,这样的话就能把"任务"本身和"线程"概念分割开来了,这样的任务就可以交给其他地方来执行
对比刚刚的第一种方法,区别就是,刚刚第一种方法是线程自己记录我要干啥,而这种写法就是别人记录我要干啥,线程只是负责执行
这种方法方便代码的解耦合

3.3匿名内部类来实现

本质上就是上面两种,只不过换了一种方法来实现

public class Demo3 {public static void main(String[] args) {Thread thread = new Thread(){@Overridepublic void run() {....}};}
}
public class Demo1 {public static void main(String[] args) throws InterruptedException {Thread t = new Thread(new Runnable() {@Overridepublic void run() {while(true){System.out.println("hello Thread");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}});t.start();while(true){System.out.println("hello main");Thread.sleep(1000);}}
}

3.5使用lambda表达式

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

我们会发现,用这种写法貌似没有重写run方法??
实际上lambda方法就是对run方法的实现,通过lambda这种方式,我们可以直接在Thread对象的构造函数中执行线程的任务逻辑,无需显示地重写run方法

感谢您的访问!!期待您的关注!!!

在这里插入图片描述

T04BF

🫵 小比特 大梦想

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

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

相关文章

【Figma】安装指南及基础操作

先前做UI设计一直都是用PS等绘图软件设计,但发现在纠结像素和排版问题上会花很多时间,再加上AI没来得及上手,就需要迅速出成图,此时通过论坛发现了figma,基本上可以满足足够的需求,并且可以在windows系统上…

SVG图标显示

SVG图标显示 1.安装SharpVectors.Wpf包 2.添加引用 xmlns:svgc"http://sharpvectors.codeplex.com/svgc/"3.加载svg文件&#xff0c;生成操作选择资源(Resource) 4.UI界面显示SVG图像 <Button Click"OnSaveFileClick" ToolTip"Save Svg File…

武汉星起航:跨境电商领域崭露头角,以实战经验引领行业新潮流

随着全球经济的演进&#xff0c;跨境电商正成为国际贸易的引擎&#xff0c;而武汉星起航电子商务有限公司凭借其丰富实战经验和专业团队&#xff0c;在这一领域取得了引人瞩目的成绩。公司成立于2020年&#xff0c;自2017年起紧紧围绕亚马逊自营店铺&#xff0c;致力于为合作伙…

基于Spring Boot+Vue的在线拍卖系统

随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统&#xff0c;主要的模块包括管理员&#xff1b;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单管理、…

初学python记录:力扣1600. 王位继承顺序

题目&#xff1a; 一个王国里住着国王、他的孩子们、他的孙子们等等。每一个时间点&#xff0c;这个家庭里有人出生也有人死亡。 这个王国有一个明确规定的王位继承顺序&#xff0c;第一继承人总是国王自己。我们定义递归函数 Successor(x, curOrder) &#xff0c;给定一个人…

通用接口开放平台设计与实现——(30)消息服务端之消息重发优化

背景 消息服务通信机制为异步&#xff0c;且网络连接不是100%可靠&#xff0c;会因为网络闪断问题丢失消息&#xff0c;作为企业应用&#xff0c;需要保证业务消息传输的可靠性&#xff0c;需实现以下机制&#xff1a; a)发送方重发机制&#xff1a;消息发送方对未收到响应的消…

酱油行业市场需求及广阔前景分析

随着居民消费升级&#xff0c;对高品质生活的向往使得酱油市场需求持续增长。消费者对酱油的功能性需求日益细分&#xff0c;追求健康、天然与个性化的产品特性&#xff0c;从而推动了市场的多元化进步。 同时&#xff0c;餐饮业的蓬勃发展以及外卖市场的扩大&#xff0c;均为酱…

【Django开发】前后端分离美多商城项目第6篇:用户部分,1. 业务说明【附代码文档】

美多商城项目4.0文档完整教程&#xff08;附代码资料&#xff09;主要内容讲述&#xff1a;美多商城&#xff0c;项目准备1.B2B--企业对企业,2.C2C--个人对个人,3.B2C--企业对个人,4.C2B--个人对企业,5.O2O--线上到线下,6.F2C--工厂到个人。项目准备&#xff0c;配置1. 修改set…

通用分布式锁组件

通用分布式锁组件 1 Redisson1.1介绍1.2 为什么要使用Redisson实现分布式锁1.2.1 锁续期的问题1.2.2 获取锁尝试的问题1.2.3 可重入问题 1.3 Wath Dog的自动延期机制1.4 快速了解1.5 项目集成 2 定义通用分布式锁组件2.1 实现思路分析2.2 定义注解2.3 定义切面2.4 使用锁2.5.工…

STL之string模拟实现

面试题&#xff1a;简易版string(深拷贝与浅拷贝的问题) 如果要实现简易版的string 无需涉及增容问题&#xff0c;成员变量可以不用存储容量和元素个数 构造函数 错误示范 class string {string(): _str(nullptr){}string(const char* str): _str(str){}char& operator[](s…

Redis数据库:高可用(主从复制、哨兵模式、cluster集群)

目录 前言 一、Redis数据库高可用 二、Redis 主从复制 1、Redis主从复制概述 1.1 Redis主从复制概念 1.2 Redis主从复制的作用 1.3 Redis主从复制的流程 2、搭建Redis主从复制 2.1 环境部署 2.2 主服务器修改配置文件 2.3 从服务器修改配置文件 2.4 测试主从复制效…

负氧离子监测站解析

TH-FZ4防腐木负氧离子监测站&#xff0c;作为一种独特的空气质量监测设备&#xff0c;以其独特的优势在生态环保领域发挥着日益重要的作用。这种监测站不仅具备防腐木材质带来的天然美感与耐久性&#xff0c;更结合了先进的负氧离子监测技术&#xff0c;为环境保护和生态旅游等…

[开源]基于SVM的时间序列预测python代码

整理了SVM的时间序列预测python代码分享给大家。记得点赞哦 #!/usr/bin/env python # coding: utf-8import numpy as np import matplotlib.pyplot as plt import pandas as pd from sklearn import preprocessing from sklearn.metrics import mean_squared_error from math i…

短剧小程序系统开发,让短剧观看与创作更加便捷。短剧系统源码搭建

一、目前短剧发展趋势 1. 市场规模&#xff1a;根据数据来看&#xff0c;2023年中国微短剧市场规模达到了373.9亿元&#xff0c;同比上升了267.65%。预计2024年市场规模将超过500亿元。这一市场规模的增长速度非常显著&#xff0c;显示出短剧行业的巨大潜力和发展前景。 2. 投…

蓝桥杯考前复习三

1.约数个数 由乘法原理可以得出&#xff1a; import java.util.*; public class Main{static int mod (int)1e9 7;public static void main(String[] args){Map<Integer,Integer> map new HashMap<>(); //创建一个哈希表Scanner scan new Scanner(System.in);i…

【会议】Oracle自动化运维峰会

2023年7月21日&#xff0c;杭州。我组织了Oracle自动化运维峰会&#xff0c;大约有20人左右参加会议。以下是会议主题&#xff1a; Oracle自动化运维能力是Oracle 19c自动化运维体系中非常重要的一环&#xff0c;自动化索引、自动化SQL优化、资源隔离等技术能够非常好的提升运维…

Java基于微信小程序的校园外卖平台系统,附源码

博主介绍&#xff1a;✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3…

C++ vector顺序表模拟实现

目录 前言&#xff1a; 模拟实现&#xff1a; 构造函数&#xff1a; 析构函数&#xff1a; 容量调整&#xff08;reserve&#xff09;&#xff1a; resize函数&#xff1a; 尾插&#xff08;push_back&#xff09;: 尾删&#xff08;pop_back&#xff09;: 插入&#xff…

C++ | Leetcode C++题解之第8题字符串转换整数atoi

题目&#xff1a; 题解&#xff1a; class Automaton {string state "start";unordered_map<string, vector<string>> table {{"start", {"start", "signed", "in_number", "end"}},{"signed…

如何判断超级充电测试的性能

超级充电测试是电动汽车充电设备性能评估的重要环节&#xff0c;其性能的好坏直接影响到电动汽车的充电效率和使用寿命。以下是判断超级充电测试性能的几个关键因素&#xff1a;这是衡量超级充电测试性能的最直接指标&#xff0c;充电速度快意味着电动汽车可以在更短的时间内完…