Java基础知识(12)

Java基础知识(12)

(包括:多线程)

目录

Java基础知识(12)

一.多线程

1. 多线程基础

2. 多线程的实现方式

【1】继承Thread类的方式进行实现

【2】实现Runnable接口的方式进行实现

【3】利用Callable接口和Future接口方式实现

3.多线程三种实现方式对比

4. 常见的成员方法

5.线程的生命周期

6. 同步代码块

7. 同步方法

8. Lock锁

9.死锁(这是一种错误)

10.生产者和消费者(等待唤醒机制)

11. 线程的状态

12. 线程池

[1]主要核心原理

[2] 线程池代码实现

【3】什么是最大并行数?

【4】线程池多大合适呢(了解)

13.多线程额外拓展(实际开发用的少,但面试的时候喜欢问)


一.多线程

1. 多线程基础

(1)什么是多线程

有了多线程,我们就可以让程序同时做多件事情

(2)多线程的作用:提高效率

(3)多线程的应用场景

只要你想让多个事情同时运行就需要用到多线程

比如:软件中的耗时操作、所有的聊天软件、所有的服务器

(2)并发和并行

1.并发:在同一时刻,有多个指令在单个CPU上交替执行

2.并行:在同一时刻,有多个指令在多个CPU上同时执行

2. 多线程的实现方式

【1】继承Thread类的方式进行实现

(1)自己定义一个类继承Thread

(2)重写run方法

(3)创建子类的对象,并启动线程

(4)案例

public class MyThread extends Thread{

@override

public void run(){

//书写线程要执行代码

for(inti=0;i<100;i++){

System.out.println("Helloworld");

}}}

public static void main(string[]args){

MyThread t1 = new MyThread();

//开启线程I

t1.start();

}

【2】实现Runnable接口的方式进行实现

(1)自己定义一个类实现Runnable接口

(2)重写里面的run方法

(3)创建自己的类的对象

(4)创建一个Thread类的对象,并开启线程

(5)案例

public class MyRun implements Runnable{

@0verride

public void run(){

//书写线程要执行的代码

for(inti=0;i<100;i++){

System.out.printin("HelloWorld!");

}}}

public static void main(string!args){

//创建MyRun的对象

//表示多线程要执行的任务

MyRun mr= new MyRun();

//创建线程对象

Thread t1 = new Thread(mr);

//开启线程

t1.start();

}

【3】利用Callable接口和Future接口方式实现

特点:可以获取到多线程运行的结果(重要)

(1)创建一个类MyCa11able实现Ca1lable接口

(2)重写ca11 (是有返回值的,表示多线程运行的结果)

(3)创建MyCallable的对象(表示多线程要执行的任务)

(4)创建FutureTask的对象(作用管理多线程运行的结果)

(5)创建Thread类的对象,并启动(表示线程)

(6)案例

public class Mycallable implements Callable<Integer>(

@0verride

public Integer call()throws Exception{

//求1~188之间的和

int sum =0;

for(inti=1;i<=100;i++){

sum = sum +i;

}

return sum;

}}

public static void main(string[]args){

//创建MyCallable的对象(表示多线程要执行的任务)

MyCallable mc = new MyCallable();

//创建FutureTask的对象(作用管理多线程运行的结果)

FutureTask<Integer>ft=new FutureTask<>(mc);

//创建线程的对象

Thread t1 = new Thread(ft);

//启动线程

t1.start();

//获取多线程运行的结果

Integer result=ft.get();

System.out.println(result);

}}

3.多线程三种实现方式对比

优点

缺点

继承Thread类

编程比较简单,可以直接使用Thread类中的方法

可以扩展性较差,不能再继承其他的类

实现Runnable接口

扩展性强,实现该接口的同时还可以继承其他的类

编程相对复杂,不能直接使用Thread类中的方法

实现Ca1lable接口

只有实现Ca1lable接口这种方法可以获取多线程的结果

4. 常见的成员方法

(1)String getName() 返回此线程的名称

(2)void setName(String name) 设置线程的名字(构造方法也可以设置名字)

(3)static Thread currentThread() 获取当前线程的对象

(4)static void sleep(long time) 让线程休眠指定的时间,单位为毫秒

(5)setPriority(int newPriority) 设置线程的优先级

(最小1,最大10,默认5)

(优先级越高只是说明抢到线程的概率高,但并不绝对)

(6)final int getPriority() 获取线程的优先级

(7)final void setDaemon(boolean on) 设置为守护线程(true为设置)

(细节:当其他的非守护线程执行完毕之后,守护线程会陆续结束)

(8)public static void yield() 出让线程/礼让线程 

(当该线程执行后会出让CPU执行权,然后所有线程重新抢夺执行器,会让线程执行的更均匀一点。)

(9)public static void join() 插入线程/插队线程

5.线程的生命周期

sleep方法会让线程睡眠,睡眠时间到了之后,立马就会执行下面的代码吗?

不会,会进入就绪态等待获得执行权。

6. 同步代码块

(1)把操作共享数据的代码锁起来

(2)格式:

synchronized(锁){

操作共享数据的代码

}

//锁对象,一定要是唯一的:static object obj= new object();

特点1:锁默认打开,有一个线程进去了,锁自动关闭

特点2:里面的代码全部执行完毕,线程出来,锁自动打开

7. 同步方法

(1)就是把synchronized关键字加到方法上

(2)格式:

修饰符 synchronized 返回值类型 方法名(方法参数) {..}

特点1:同步方法是锁住方法里面所有的代码

特点2:锁对象不能自己指定,由Java指定

非静态方法: this(锁对象)

静态方法:当前类的字节码文件对象(锁对象)(一般用这个!!!)

(3)StringBuilder和StringBuffer

两者的方法基本相同,但StringBuilder在多线程时不安全,此时应用StringBuffer

8. Lock锁

(1)产生原因

虽然我们可以理解同步代码块和同步方法的锁对象问题

但是我们并没有直接看到在哪里加上了锁,在哪里释放了锁

为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock

Lock实现提供比使用synchronized方法和语句可以获得更广泛的锁定操作

(2)方法

Lock中提供了获得锁和释放锁的方法

void lock():获得锁 手动上锁

void unlock():释放锁 手动释放锁

(3)创建

Lock是接口不能直接实例化,这里采用它的实现类ReentrantLock来实例化

ReentrantLock的构造方法

ReentrantLock():创建一个ReentrantLock的实例

(4)案例

public void run(){

while(true){

//同步代码块

Lock.lock();//2 //3

try {

if(ticket == 100){

break;

}else{

Thread.sleep(10);

ticket++;

System.out.println(getName())

}

}catch(InterruptedException e){

e.printstackTrace();

} finally{

Lock.unlock();

}

Try-catch-finally可以确保一定会释放锁。

9.死锁(这是一种错误)

以后注意千万不要让两个锁嵌套起来

10.生产者和消费者(等待唤醒机制)

生产者消费者模式是一个十分经典的多线程协作的模式

[1]消费者执行过程

(1)判断東子上是否有食物

(2)如果没有就等待

(3)如果有就开吃

(4)吃完之后,唤醒厨师继续做

[2] 生产者执行过程

(1)判断桌子上是否有食物

(2)有:等待

(3)没有:制作食物

(4)把食物放在桌子上

(5)叫醒等待的消费者开吃

[3] 生产者和消费者(常见方法)

void wait() 当前线程等待,直到被其他线程唤醒

void notify() 随机唤醒单个线程

void notifyA11() 唤醒所有线程

synchronized(Desk.lock){

Desk.lock.wait();//让当前线程跟锁进行绑定,不然一会唤醒总不能把电脑所以进程都唤醒吧

Desk.lock.notifyA11();

}

[3] 等待唤醒机制(阻塞队列方式实现)

(1)put数据时:放不进去,会等着,也叫做阻塞。

(2)take数据时:取出第一个数据,取不到会等着,也叫做阻塞。

(3)阻塞队列内部有锁,再把它写在里面就会形成死锁

(4)ArrayBlockingQueue:底层是数组,有界

(5)LinkedBlockingQueue:底层是链表,无界,但不是真正的无界,最大为int的最大值。

(6)细节:生产者和消费者必须使用同一个阻塞队列(在main中创建)

11. 线程的状态

(1)新建状态(NEW)    --> 创建线程对象

(2)就绪状态(RUNNABLE)      à start方法

(3)阻塞状态(BLOCKED)       à无法获得锁对象

(4)等待状态(WAITING)        àwait方法

(5)计时等待(TIMED WAITING)       àsleep方法

(6)结束状态(TERMINATED)       à全部代码运行完毕

12. 线程池

[1]主要核心原理

① 创建一个池子,池子中是空的

② 提交任务时,池子会创建新的线程对象,任务执行完毕,线程归还给池子

下回再次提交任务时,不需要创建新的线程,直接复用已有的线程即可

③ 但是如果提交任务时,池子中没有空闲线程,也无法创建新的线程,任务就会排队等待

[2] 线程池代码实现

(1)步骤

①创建线程池

②提交任务

③所有的任务全部执行完毕,关闭线程池(一般不会关闭)

(2)方法

Executors:线程池的工具类通过调用方法返回不同类型的线程池对象。

public static ExecutorService newCachedThreadPool() 创建一个没有上限的线程池(最大为int的最大值。)

public static ExecutorService newFixedThreadPool(int nThreads) 创建有上限的线程池

(3)案例

//1.获取线程池对象

ExecutorService pool1 = Executors.newCachedThreadPool()

//2.提交任务

poo11.submit(new MyRunnable());

//3.销毁线程池

poo11.shutdown();

【3】什么是最大并行数?

如:电脑为4核8线程,则最大并行数为8

//向Java点拟机返回可用处理器的数目

int count =Runtime.getRuntime().availableProcessors();

System.out.println(count);

即可获取本电脑的最大并行数

【4】线程池多大合适呢(了解)

CPU 密集型运算 最大并行数 +1(计算多)

I/0 密集型运算 最大并行数*期望CPU 利用率*总时间(CPU计算时间+等待时间)/ CPU计算时间(读取数据多)

13.多线程额外拓展(实际开发用的少,但面试的时候喜欢问)

在仅我可见中

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【大学物理】双语笔记

7.5 angular momentu(角动量)_哔哩哔哩_bilibili 6.4Energy in Rotation Motion 有质量有速度的物体有动能&#xff0c;是不是很有道理 international system&#xff08;from French systeme international&#xff0c;acronym&#xff0c;SI&#xff09;of ineria kg*m^2 转…

uniapp——弹出键盘遮挡住输入框 textarea,处理方法

案例 在写输入框的时候会遇见 键盘遮挡住部分textarea框的一部分&#xff0c;使用cursor-spacing处理即可 修改后&#xff1a; 其他问题&#xff1a; 调起键盘输入时&#xff0c;不希望上方的内容被顶上去 代码 <view class"commentBox" :style"botto…

上亿用户面临风险!小米、WPS等知名安卓应用竟藏有“文件覆盖”漏洞

Google Play商店中的几款热门安卓应用程序容易受到与路径遍历相关的漏洞攻击&#xff0c;该漏洞的代号为“Dirty Stream”攻击&#xff0c;恶意应用程序可能会利用此漏洞覆盖易受攻击的应用程序主目录中的任意文件。 微软威胁情报团队的Dimitrios Valsamaras在周三发布的一份报…

实现C++ Vector

手写C Vector&#xff0c;参考QVector 类声明 template<typename T >class IteratorVector;template<typename T >class IteratorVectorConst;template<typename T >class Vector final :public ContainerBase{public:explicit Vector()noexcept;explicit V…

如何使用Reqable脚本功能提高API开发效率

Reqable支持使用Python脚本对API开发和调试进行辅助&#xff0c;今天写一篇实战教程&#xff0c;由浅入深地演示下如何使用Reqable的脚本功能。 首先&#xff0c;电脑上需要安装Python软件包。一般情况下&#xff0c;系统都会预安装Python软件包&#xff0c;如果系统没有安装或…

大语言模型LLM应用篇

大模型席卷全球&#xff0c;彷佛得模型者得天下。对于IT行业来说&#xff0c;以后可能没有各种软件了&#xff0c;只有各种各样的智体&#xff08;Agent&#xff09;调用各种各样的API。在这种大势下&#xff0c;笔者也阅读了很多大模型相关的资料&#xff0c;和很多新手一样&a…

升级到 AGP7+,适配 assets 目录了吗

我们知道 assets 文件处理的任务是 merge[变体名称]ReleaseAssets&#xff0c;例如&#xff1a; mergeCommonReleaseAssetsmergeReleaseAssetsmergeDebugAssets 在 AGP 升级过程中&#xff0c;不同的 Android Gradle Plugin 版本打包过程中处理 assets 文件的临时目录可能存在…

[笔试训练](十七)

目录 049:小乐乐改数字 050:十字爆破 051:比那名局的桃子 049:小乐乐改数字 小乐乐改数字_牛客题霸_牛客网 (nowcoder.com) 题目&#xff1a; 题解&#xff1a; 把输入的数字当成字符串&#xff0c;按字符一个一个读&#xff0c;边读边按条件改成字符0或1。 #include &l…

2024 年 数维杯(A题)大学生数学建模挑战赛 | 多源机会信号建模| 数学建模完整代码+建模过程全解全析

2024数维杯数学建模A题B题C题思路模型代码&#xff08;开赛后第一时间更新&#xff09;及时留意关注哦 https://mbd.pub/o/bread/ZpWakpdq https://mbd.pub/o/bread/ZpWakpdq 2024数维杯数学建模A题B题C题思路模型代码&#xff08;开赛后第一时间更新&#xff09;及时留意关注…

每周一算法:无向图的最小环

题目链接 观光之旅 题目描述 给定一张无向图&#xff0c;求图中一个至少包含 3 3 3 个点的环&#xff0c;环上的节点不重复&#xff0c;并且环上的边的长度之和最小。 该问题称为无向图的最小环问题。 你需要输出最小环的方案&#xff0c;若最小环不唯一&#xff0c;输出…

SG3225EEN在PAM4光模块和400G,QSFP-DD光模块中的应用

爱普生晶振SG3225EEN&#xff0c;156.25MHz在PAM4光模块和QSFP-DD光模块中的应用。光模块市场已发展至400G光模块&#xff0c;那么PAM4光模块和400G QSFPDD光模块有哪些区别呢?SG3225EEN又是怎么应用在PAM4光模块和QSFP-DD光模块中的呢? 首先介绍的是PAM4光模块:PAM4是PAM(脉…

android基础-服务

同样使用intent来传递服务 oncreate是服务第一次启动调用&#xff0c;onStartCommand是服务每次启动的时候调用&#xff0c;也就是说服务只要启动后就不会调用oncreate方法了。可以在myservice中的任何位置调用stopself方法让服务停止下来。 服务生命周期 前台服务类似于通知会…

「ETL实战」搭建数仓,解决多源业务系统关联分析难题(定制化业务)

在大数据分析盛行的今天&#xff0c;关联分析作为数据挖掘和业务洞察的重要手段&#xff0c;受到了极大关注。然而&#xff0c;随着数据量的激增和源业务系统的复杂性增加&#xff0c;关联分析的性能问题逐渐成为了一个不可忽视的挑战。 本文将介绍借助ETL工具&#xff0c;如何…

Go 语言基础之常用包【flag、time、strconv、io】

1、命令行参数包 flag flag 包就是一个用来解析命令行参数的工具。 1.1、os.Args import ("fmt""os" )func main() {if len(os.Args) > 0 {for index, arg : range os.Args {fmt.Printf("args[%d]%v\n", index, arg)}} } 运行结果&#…

Windows程序设计课程作业-2(音乐文件播放功能)

目录 1、作业内容 要求1&#xff1a; 提示&#xff1a; 要求2&#xff1a; 提示&#xff1a; 作业提交方式: 2、主要思路 1&#xff09;准备工作 2&#xff09;提取音乐文件功能 3&#xff09;选择音乐进行播放 4&#xff09;异常信息进行处理 5&#xff09;停止播…

【最新点云数据增强综述】深度学习点云数据增强技术的进展

深度学习(DL)已成为点云分析任务(如检测、分割和分类)的主流和有效方法之一。为了减少深度学习模型训练过程中的过拟合,提高模型性能,尤其是在训练数据的数量和/或多样性有限的情况下,增强往往至关重要。虽然各种点云数据增强方法已被广泛应用于不同的点云处理任务中,但…

[muduo网络库]——muduo库的Reactor模型(剖析muduo网络库核心部分、设计思想)

一、前言 在学习 C 服务端的过程中&#xff0c;必不可少的一项就是熟悉一个网络库&#xff0c;包括网络库的应用和其底层实现。我们熟知的网络库有 libevent、libev、muduo、Netty 等&#xff0c;其中 muduo 是由陈硕大佬个人开发的 TCP 网络库&#xff0c;最近跟着课程正在深…

Springboot+Vue项目-基于Java+MySQL的车辆管理系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

Java方法和数组

方法 Java中的方法就是c语言中的函数。 方法的定义 定义格式如下 修饰符 返回值 方法名([参数列表]){代码块[return 返回值;] } //方括号[]括起来代表可以没有&#xff0c;不是必须有的方法名采用小驼峰命名&#xff08;就是有多个单词&#xff0c;第一个单词首字母小写其…

Redis学习1——redis简介、基础

介绍 redis简介 Redis(Remote Dictonary Server) 是由Salvatore Sanfilippo开发的key-value缓存数据库&#xff0c;基于C语言开发。目前市面上&#xff0c;Redis和MongoDB是当前使用最广泛的NoSQL&#xff0c;而就Redis技术而言&#xff0c;它的性能十分优越&#xff0c;可以…
最新文章