Java多线程开发——基础篇

目录

1.基本概念

2.创建线程方式

2.1直接建立线程

2.2实现Runnable接口

3.3实现Callable接口

3.4 了解Future接口

Future模式主要角色及其作用

3.5实例化FutureTask类

3.实现线程安全

3.1定义

3.2不安全原因

3.3解决方案

3.4volatile与synchronized区别

4.极端情况——线程死锁

4.1定义

4.2解决措施

5.多线程通信

6.线程池的掌握

6.1核心参数

6.2常见线程池

6.3自定义线程池

6.4操作步骤


1.基本概念

线程状态:新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)、

                  等待(Waiting)、超时等待(Timed Waiting)、终止(Terminated)

锁(同步监视器):分为悲观锁和乐观锁,常见的有偏向锁、轻量级锁、重量级锁

                                CAS(Compare And Swap)是一种乐观锁的实现方式,通过比较并

                                交换来实现并发控制

2.创建线程方式

Runnable接口、Callable接口、Future接口、FutureTask类

2.1直接建立线程

        创建Thread子类,按需求重写run()方法 【run代表此线程执行时会做的事】

        这里的属性若为 多线程共享属性,加static修饰

2.2实现Runnable接口

 这里的 多线程共享属性 可以是非静态的,因为多线程共用此接口

3.3实现Callable接口

(1)实现接口Callable,重写call()回调方法,会返回一个值,值类型由Callable泛型决定

实例化上述类,利用FutureTask(Callable)构造器实例化类

3.4 了解Future接口

异步调用的多线程开发模式之一(异步:当我们需要调用一个函数方法时,并不急着要结果。让被调者立即返回,让它在后台慢慢处理这个请求;此时则可以先处理一些其他任务

Future模式主要角色及其作用

Main->调用Client发送请求

Data->返回数据的接口

Client->返回Data对象,立即返回FutureData,并开启ClientThread线程装配RealData

FutureData->虚拟数据,伪造数据立即返回,最终装配上RealData

RealData->真实数据,构造缓慢

3.5实例化FutureTask类

FutureTask用于异步获取执行结果或取消执行任务

通过传入Runnable或者Callable的任务给FutureTask,

直接调用其run方法或者放入线程池执行,

最后在外部通过FutureTask的get方法异步获取执行结果(适合耗时操作)

3.实现线程安全

3.1定义

多线程环境下,对共享资源的访问不会导致数据出错。

因此和单线程执行相同的操作,结果相同

3.2不安全原因

1. 线程是抢占式的执行,线程间的调度充满了随机性
2. 多个线程对同一个变量进行修改操作
3. 对变量的操作不是原子性的
4. 内存可见性导致的线程安全问题
5. 指令重排序也会影响线程安全

3.3解决方案

使用同步机制(如synchronized、Lock)、

使用线程安全的数据结构(如ConcurrentHashMap)

synchronized:Java关键字,属于隐式锁,可以修饰方法或代码块

Lock:JAVA接口,显式锁

原理上都是通过对共享资源加锁来实现同步。

3.4volatile与synchronized区别

volatile关键字用于保证变量的可见性

而synchronized既保证可见性又保证原子性

volatile适用于单个变量的读写操作,而synchronized适用于复合操作或临界区。

4.极端情况——线程死锁

4.1定义

多个线程相互等待对方释放资源,导致无法继续执行

4.2解决措施

  1. 避免嵌套锁、

  2. 按固定的顺序获取锁、

  3. 设置超时时间、

  4. 使用Lock对象代替synchronized关键字。

5.多线程通信

通过共享变量、wait()和notify()、BlockingQueue等机制来实现线程间的数据交换和协作

6.线程池的掌握

6.1核心参数

核心线程数(corePoolSize):依据任务的处理时间和每秒产生的任务数量来确定

最大线程数(maximumPoolSize):参照核心线程数和系统每秒产生的最大任务数决定

线程空闲时间(keepAliveTime):用户自设置合理时间间隔

任务队列长度:(workQueue):大于等于任务队列长度,就丢弃多的任务

6.2常见线程池

FixedThreadPool、CachedThreadPool、ScheduledThreadPool

6.3自定义线程池

1:编写任务类(MyTask),实现Runnable接口;
2:编写线程类(MyWorker),用于执行任务,需要持有所有任务;
3:编写线程池类(MyThreadPool),包含提交任务,执行任务的能力;
4:编写测试类(MyTest),创建线程池对象,提交多个任务测试;

如下模板:

package com.itheima.demo01;import java.util.Collections;
import java.util.LinkedList;
import java.util.List;/*这是自定义的线程池类;成员变量:1:任务队列   集合  需要控制线程安全问题2:当前线程数量3:核心线程数量4:最大线程数量5:任务队列的长度成员方法1:提交任务;将任务添加到集合中,需要判断是否超出了任务总长度2:执行任务;判断当前线程的数量,决定创建核心线程还是非核心线程*/
public class MyThreadPool {// 1:任务队列   集合  需要控制线程安全问题private List<Runnable> tasks = Collections.synchronizedList(new LinkedList<>());//2:当前线程数量private int num;//3:核心线程数量private int corePoolSize;//4:最大线程数量private int maxSize;//5:任务队列的长度private int workSize;public MyThreadPool(int corePoolSize, int maxSize, int workSize) {this.corePoolSize = corePoolSize;this.maxSize = maxSize;this.workSize = workSize;}//1:提交任务;public void submit(Runnable r){//判断当前集合中任务的数量,是否超出了最大任务数量if(tasks.size()>=workSize){System.out.println("任务:"+r+"被丢弃了...");}else {tasks.add(r);//执行任务execTask(r);}}//2:执行任务;private void execTask(Runnable r) {//判断当前线程池中的线程总数量,是否超出了核心数,if(num < corePoolSize){new MyWorker("核心线程:"+num,tasks).start();num++;}else if(num < maxSize){new MyWorker("非核心线程:"+num,tasks).start();num++;}else {System.out.println("任务:"+r+" 被缓存了...");}}}

6.4操作步骤

1:利用Executors工厂类的静态方法,创建线程池对象;
2:编写Runnable或Callable实现类的实例对象;
3:利用ExecutorService的submit方法或ScheduledExecutorService的schedule方    法提交并执行线程任务
4:如果有执行结果,则处理异步执行结果(Future)
5:调用shutdown()方法,关闭线程池

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

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

相关文章

Docker 学习笔记(三):Centos7 中 Docker 使用,镜像、容器,以及操作等常用命令小结

一、前言 记录时间 [2024-4-7] 前置文章&#xff1a; Docker学习笔记&#xff08;一&#xff09;&#xff1a;入门篇&#xff0c;Docker概述、基本组成等&#xff0c;对Docker有一个初步的认识 Docker学习笔记&#xff08;二&#xff09;&#xff1a;在Linux中部署Docker&#…

(Java)数据结构——排序(第一节)堆排序+PTA L2-012 关于堆的判断

前言 本博客是博主用于复习数据结构以及算法的博客&#xff0c;如果疏忽出现错误&#xff0c;还望各位指正。 堆排序&#xff08;Heap Sort&#xff09;概念 堆排序是一种基于堆数据结构的排序算法&#xff0c;其核心思想是将待排序的序列构建成一个最大堆&#xff08;或最小…

从库延迟案例分析

背景介绍 近来一套业务系统&#xff0c;从库一直处于延迟状态&#xff0c;无法追上主库&#xff0c;导致业务风险较大。从资源上看&#xff0c;从库的CPU、IO、网络使用率较低&#xff0c;不存在服务器压力过高导致回放慢的情况&#xff1b;从库开启了并行回放&#xff1b;在从…

Python —— 简述

Houdini Python | 笔记合集 - 知乎 Houdini内置三大语言&#xff1a; 表达式&#xff0c;主要用于节点参数控制&#xff0c;可实现跨模块控制&#xff1b;vex&#xff0c;速度最快&#xff08;比表达式和Python快一个数量级&#xff09;&#xff0c;非常适合密集型计算环境&…

【React】Ant Design社区扩展库之分割面板:react-resizable-panels

主角&#xff1a;react-resizable-panels 简介&#xff1a;来之Ant Design官方文档社区精选组件 1、效果 2、环境 react-resizable-panels: ^2.0.16next: 14.1.3react: ^18 3、安装 # npm npm install react-resizable-panels# yarn yarn add react-resizable-panels# pnpm …

Docker学习笔记(二):在Linux中部署Docker(Centos7下安装docker、环境配置,以及镜像简单使用)

一、前言 记录时间 [2024-4-6] 前置文章&#xff1a;Docker学习笔记&#xff08;一&#xff09;&#xff1a;入门篇&#xff0c;Docker概述、基本组成等&#xff0c;对Docker有一个初步的认识 在上文中&#xff0c;笔者进行了Docker概述&#xff0c;介绍其历史、优势、作用&am…

《三》按钮---PushButton和信号槽机制

QPushButton按钮用法详解 按钮是 GUI 开发中最常用到的一种控件&#xff0c;作为一款著名的 GUI 开发框架&#xff0c;Qt 提供了很多种按钮&#xff0c;比如 QPushButton&#xff08;普通按钮&#xff09;、QRadioButton&#xff08;单选按钮&#xff09;、QToolButton&#x…

对LSTM的通俗易懂理解--可变权重

RNN的问题&#xff1a;长期依赖&#xff0c;即对短期的数据敏感&#xff0c;对比较远的长期数据不敏感&#xff0c;这是因为RNN隐藏状态权重在不同时刻是共享相同的&#xff0c;随着时间步的增加&#xff0c;梯度会指数级地衰减或者增长&#xff0c;导致梯度消失或者爆炸&#…

【黑马头条】-day06自媒体文章上下架-Kafka

文章目录 今日内容1 Kafka1.1 消息中间件对比1.2 kafka介绍1.3 kafka安装及配置1.4 kafka案例1.4.1 导入kafka客户端1.4.2 编写生产者消费者1.4.3 启动测试1.4.4 多消费者启动 1.5 kafka分区机制1.5.1 topic剖析 1.6 kafka高可用设计1.7 kafka生产者详解1.7.1 同步发送1.7.2 异…

配置vlan和vlan间路由、配置vlan的ip和vrrp、mstp和主次根

简单的通信实验 拓扑图&#xff1a; 1.配置vlan和链路聚合 Sw1 & sw2 undo info-center enable vlan batch 10 20 30 40 int eth-trunk 1 trunkport g 0/0/1 to 0/0/2 port link-type trunk port trunk allow-pass vlan 10 20 30 40 int g0/0/3 port link-type trunk p…

Unity 布局 HorizontalLayoutGroup 多行 换行

演示Gif&#xff1a; 现象: 子元素宽度不同&#xff0c;超出父元素后不会换行 GridLayout则是固定宽度也不能用&#xff0c; 需求 水平排版的同时&#xff0c;超出父级后换行 代码&#xff1a; 催更就展示[狗头]

Linux:Redis7.2.4的简单在线部署(1)

注意&#xff1a;我写的这个文章是以最快速的办法去搭建一个redis的基础环境&#xff0c;作用是为了做实验简单的练习&#xff0c;如果你想搭建一个相对稳定的redis去使用&#xff0c;可以看我下面这个文章 Linux&#xff1a;Redis7.2.4的源码包部署&#xff08;2&#xff09;-…

CSS 基础:设置背景的 5 个属性及简写 background 注意点

你好&#xff0c;我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端的程序媛。大专生&#xff0c;一枚程序媛&#xff0c;感谢关注。回复 “前端基础题”&#xff0c;可免费获得前端基础 100 题汇总&#xff0c;回复 “前端工具”&#xff0c;可获取 Web 开发工具合集 263篇…

给你的Qt软件加个授权

写在前面 环境&#xff1a; Win11 64位 VS2019 Qt5.15.2 核心思路&#xff1a; 将授权相关信息加密保存到License.txt中&#xff0c;软件运行时获取并解密授权信息&#xff0c;判断是否在限制期限内即可。 加解密部分使用第三方openssl库进行&#xff0c;因此需要手动在…

家庭网络防御系统搭建-虚拟机安装siem/securityonion网络连接问题汇总

由于我是在虚拟机中安装的security onion&#xff0c;在此过程中&#xff0c;遇到很多的网络访问不通的问题&#xff0c;通过该文章把网络连接问题做一下梳理。如果直接把securityonion 安装在物理机上&#xff0c;网络问题则会少很多。 NAT无法访问虚拟机 security onion虚拟…

多目标跟踪 | 基于anchor-free目标检测+ReID的实时一阶多类多目标跟踪算法实现

项目应用场景 面向多目标检测跟踪场景&#xff0c;项目采用 anchor-free 目标检测ReID 的实时一阶段多类多目标跟踪算法实现&#xff0c;效果嘎嘎好。 项目效果 项目细节 > 具体参见项目 README.md (1) 类别支持 1~10 object classes are what we need non-interest-…

SpringCloud学习(9)-GateWay网关-自定义拦截器

GateWay Filter详细配置说明 gateway Filter官网:Spring Cloud Gateway 作用&#xff1a; 请求鉴权异常处理记录接口调用时长统计 过滤器类别 全局默认过滤器&#xff1a;官网&#xff1a;Spring Cloud Gateway&#xff0c;出厂默认已有的&#xff0c;直接用&#xff0c;作…

Qt栅格布局的示例

QGridLayout * layoutnew QGridLayout;for(int i0;i<10;i){for(int j0;j<6;j){QLabel *labelnew QLabel(this);label->setText(QString("%1行%2列").arg(i).arg(j));layout->addWidget(label,i,j);}}ui->widget->setLayout(layout); 这样写程序会崩…

【vue】v-bind动态属性绑定

v-bind 简写:value <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><styl…

NC65 查询默认密码(sql)

NC65 使用sql查询设置的默认密码&#xff08;如果系统设置有&#xff09;&#xff1a; select * from sm_user_defaultpwd