wordpress 755/郑州谷歌优化外包

wordpress 755,郑州谷歌优化外包,广告联盟推广,哪个网站做税务登记原理 通过用一个goroutine以及堆来存储要待调度的延迟任务,当达到调度时间后,将其添加到协程池中去执行。 主要是使用了chan、Mutex、atomic及ants协程池来实现。 用途 主要是用于高并发及大量定时任务要处理的情况,如果使用Go协程来实现每…

原理

通过用一个goroutine以及堆来存储要待调度的延迟任务,当达到调度时间后,将其添加到协程池中去执行。
主要是使用了chan、Mutex、atomic及ants协程池来实现。

用途

主要是用于高并发及大量定时任务要处理的情况,如果使用Go协程来实现每次延迟任务的调度,那么数量极大的goroutine将会占用内存,导致性能下降,使用协程池实现延迟任务的调度,会改善该情况。
如在物联网设备中,当连接数量达到几十万时,如果使用goroutine来处理心跳或者活跃检测,频繁的创建销毁goroutine会影响性能。

特色

在常见的cron等开源框架中使用的是数组存储待调度的任务,每次循环时都要排序,并且要删除某个任务则时间复杂度是O(n)。

本文通过使用堆及双重Map优化存储待调度的任务,使得添加任务时间复杂度为O(log n),获取任务时间复杂度为O(1),删除时间复杂度为O(1)。

调度器并不会真正的删除取消任务,当取消任务达到执行时间时,会直接continue,是为了提高删除效率,如果要删除取消任务,那么删除的时间复杂度为O(log n),当有极大量任务时,会占用一些内存,通过空间换时间来提高删除效率,下文也提供了删除取消任务的实现,根据不同的场景使用不同的定时任务。

API

创建

NewSchedule(workerNum int, options ...ants.Option) (*Schedule, error) //创建协程数是1的延迟任务调度器
s, _ := NewSchedule(1)

创建一个延迟调度任务器,workerNum是协程数量,options是ants协程池的配置,除了WithMaxBlockingTasks不能配置,别的都可以,具体参考:https://github.com/panjf2000/ants

调度一次

func (s *Schedule) ScheduleOne(job func(), duration time.Duration) (TaskId, error) //1秒后打印一次时间
taskId, _ := s.ScheduleOne(func() {fmt.Println(time.Now())
}, time.Second)

重复调度

func (s *Schedule) Schedule(job func(), duration time.Duration) (TaskId, error) //每隔一秒打印一次时间
taskId, _ := s.Schedule(func() {fmt.Println(time.Now())
}, time.Second)

取消调度

func (s *Schedule) Schedule(job func(), duration time.Duration) (TaskId, error) //每隔一秒打印一次时间
taskId, _ := s.Schedule(func() {fmt.Println(time.Now())
}, time.Second)
//休眠3秒后,取消调度
time.Sleep(3 * time.Second)
s.CancelTask(taskId)

停止调度

func (s *Schedule) Schedule(job func(), duration time.Duration) (TaskId, error) //每隔一秒打印一次时间
taskId, _ := s.Schedule(func() {fmt.Println(time.Now())
}, time.Second)
//休眠3秒后,停用延迟任务调度器
time.Sleep(3 * time.Second)
s.Shutdown()

代码

package scheduleimport ("container/heap""errors""github.com/panjf2000/ants/v2""math""sync/atomic""time"
)var (// ErrScheduleShutdown 延迟任务调度器已关闭错误ErrScheduleShutdown = errors.New("schedule: schedule is already in shutdown")
)const invalidTaskId = 0type TaskId uint32
type OriginalTaskId uint32// Schedule 延迟调度的结构体,提供延迟调度任务的全部方法
// 通过NewSchedule方法创建Schedule,通过Schedule、ScheduleOne方法添加延迟调度任务,通过CancelTask方法取消任务,通过Shutdown停止延迟任务
type Schedule struct {//任务堆,按时间排序taskHeap taskHeap//可执行的任务Map,key是当前的任务id,value是任务的第一次原始id,用于优化取消任务时需要遍历堆去删除executeTaskIdMap map[TaskId]OriginalTaskId//任务id的Map,key是任务的第一次原始id,value是当前的任务id,用于优化取消任务时需要遍历堆去删除originalTaskIdMap map[OriginalTaskId]TaskId//调度器是否运行中running atomic.Bool//下一个任务idnextTaskId atomic.Uint32//任务运行池pool *ants.Pool//添加任务ChanaddTaskChan chan *Task//删除任务ChanstopTaskChan chan struct{}//取消任务ChancancelTaskChan chan OriginalTaskId
}// NewSchedule 构建一个Schedule
// workerNum 工作的协程数量,options ants协程池的配置,除了WithMaxBlockingTasks不能配置,别的都可以,具体参考:https://github.com/panjf2000/ants
func NewSchedule(workerNum int, options ...ants.Option) (*Schedule, error) {//延迟任务的最大任务数量必须不限制options = append(options, ants.WithMaxBlockingTasks(0))//创建一个协程池pool, err := ants.NewPool(workerNum)if err != nil {return nil, err}//创建一个延迟调度结构体s := &Schedule{taskHeap:          make(taskHeap, 0),executeTaskIdMap:  make(map[TaskId]OriginalTaskId),originalTaskIdMap: make(map[OriginalTaskId]TaskId),running:           atomic.Bool{},nextTaskId:        atomic.Uint32{},pool:              pool,addTaskChan:       make(chan *Task),stopTaskChan:      make(chan struct{}),cancelTaskChan:    make(chan OriginalTaskId),}//启动调度 会开启一个协程去将即将要调度的任务添加到协程池中运行s.start()return s, nil
}// ScheduleOne 添加延迟调度任务,只调度一次
// job 执行的方法 duration 周期间隔,如果是负数立马执行,如果是负数立马且只执行一次
func (s *Schedule) ScheduleOne(job func(), duration time.Duration) (uint32, error) {return s.doSchedule(job, duration, true)
}// Schedule 添加延迟调度任务,重复调度
// job 执行的方法 duration 周期间隔,如果是负数立马且只执行一次
func (s *Schedule) Schedule(job func(), duration time.Duration) (uint32, error) {return s.doSchedule(job, duration, false)
}// doSchedule 添加延迟调度任务的具体实现
func (s *Schedule) doSchedule(job func(), duration time.Duration, onlyOne bool) (uint32, error) {if s.running.Load() {//如果是负数 只执行一次if duration <= 0 {onlyOne = true}nextTaskId := s.getNextTaskId()task := new(Task)task.job = jobtask.executeTime = time.Now().Add(duration)task.onlyOne = onlyOnetask.duration = durationtask.originalId = OriginalTaskId(nextTaskId)task.id = TaskId(nextTaskId)s.addTaskChan <- taskreturn uint32(task.originalId), nil} else {return invalidTaskId, ErrScheduleShutdown}
}// CancelTask 取消延迟调度任务
// taskId 任务id
func (s *Schedule) CancelTask(taskId uint32) {if s.running.Load() {if taskId != invalidTaskId {s.cancelTaskChan <- OriginalTaskId(taskId)}}
}// Shutdown 结束延迟任务调度
func (s *Schedule) Shutdown() {//通过cas设值if s.running.CompareAndSwap(true, false) {s.stopTaskChan <- struct{}{}}
}// IsShutdown 延迟任务调度是否关闭
func (s *Schedule) IsShutdown() bool {return !s.running.Load()
}// start 启动延迟任务调度
func (s *Schedule) start() {s.running.Store(true)go func() {for {now := time.Now()var timer *time.Timer//如果没有任务提交,睡眠等待任务if s.taskHeap.Len() == 0 {timer = time.NewTimer(math.MaxUint16 * time.Hour)} else {//查看第一个要执行的任务是否是被取消的task := s.taskHeap.Peek()_, ok := s.executeTaskIdMap[task.id]if !ok {//是被取消的任务,移除后continueheap.Pop(&s.taskHeap)continue} else {//设置执行间隔timer = time.NewTimer(task.executeTime.Sub(now))}}select {case <-timer.C://到达第一个任务执行时间task := heap.Pop(&s.taskHeap).(*Task)//提交到线程池执行,返回的error不需要处理,因为任务池是无限大_ = s.pool.Submit(task.job)//单次执行则删除,多次执行,则更新if task.onlyOne {s.removeTask(task.originalId, task.id)} else {s.updateTask(task)}case originalTaskId := <-s.cancelTaskChan:timer.Stop()//如果取消的任务id在待执行任务列表中,则删除任务if taskId, ok := s.originalTaskIdMap[originalTaskId]; ok {s.removeTask(originalTaskId, taskId)}case task := <-s.addTaskChan:timer.Stop()//添加任务s.addTask(task)case <-s.stopTaskChan:timer.Stop()//关闭资源s.close()return}}}()
}// updateTask 更新延迟调度任务
func (s *Schedule) updateTask(executedTask *Task) {//拷贝 并设置新的执行时间和IDtask := *executedTasktask.executeTime = time.Now().Add(task.duration)nextTaskId := s.getNextTaskId()task.id = TaskId(nextTaskId)//把已执行的任务删除s.removeTask(invalidTaskId, executedTask.id)//添加新的任务s.addTask(&task)
}// removeTask 移除任务
func (s *Schedule) removeTask(originalTaskId OriginalTaskId, taskId TaskId) {//如果原始的任务ID不为空,则为使用者取消的,从任务Map中也删除if originalTaskId != invalidTaskId {delete(s.originalTaskIdMap, originalTaskId)}delete(s.executeTaskIdMap, taskId)
}// addTask 添加任务
func (s *Schedule) addTask(task *Task) {s.originalTaskIdMap[task.originalId] = task.ids.executeTaskIdMap[task.id] = task.originalIdheap.Push(&s.taskHeap, task)
}// getNextTaskId 获取下一个任务id
func (s *Schedule) getNextTaskId() uint32 {taskId := s.nextTaskId.Add(1)if taskId == invalidTaskId {taskId = s.nextTaskId.Add(1)}return taskId
}// close 关闭Schedule资源和协程池的资源
func (s *Schedule) close() {//关闭所有资源并设置为 nil help gcs.taskHeap = nils.executeTaskIdMap = nils.originalTaskIdMap = nils.pool.Release()s.pool = nilclose(s.addTaskChan)close(s.cancelTaskChan)close(s.stopTaskChan)s.addTaskChan = nils.cancelTaskChan = nils.stopTaskChan = nil
}// Task 调度任务结构体,是一个调度任务的实体信息
type Task struct {// 原始id,用于Schedule本身的删除使用,用两层Map的方式优化数组删除的O(n)时间复杂度originalId OriginalTaskId// 任务idid TaskId// 执行的时间,每次执行完,如果重复调度就重新计算executeTime time.Time// 周期间隔duration time.Duration// 执行的任务job func()// 是否只执行一次onlyOne bool
}// 任务的堆,使用队只需要在添加的时候进行排序,堆顶是最先要执行的任务
type taskHeap []*Task// 下面都是堆接口的实现func (t *taskHeap) Len() int {return len(*t)
}
func (t *taskHeap) Less(i, j int) bool {return (*t)[i].executeTime.Before((*t)[j].executeTime)
}func (t *taskHeap) Swap(i, j int) {(*t)[i], (*t)[j] = (*t)[j], (*t)[i]
}func (t *taskHeap) Push(x interface{}) {*t = append(*t, x.(*Task))
}func (t *taskHeap) Pop() interface{} {old := *tn := len(old)x := old[n-1]old[n-1] = nil*t = old[:n-1]return x
}// Peek 查看堆顶元素,非堆接口的实现
func (t *taskHeap) Peek() *Task {return (*t)[0]
}

代码加上详细的中文注解,大约300行。
github地址:
https://github.com/xzc-coder/go-schedule

另一个版本的实现,删除时间复杂度为:O(log n),相对上文中的实现,占用的内存会少,但是删除效率会变低。

package scheduleimport ("container/heap""errors""github.com/panjf2000/ants/v2""math""sync/atomic""time"
)var (// ErrScheduleShutdown 延迟任务调度器已关闭错误ErrScheduleShutdown = errors.New("schedule: schedule is already in shutdown")
)const invalidTaskId = 0type TaskId uint32// Schedule 延迟调度的结构体,提供延迟调度任务的全部方法
// 通过NewSchedule方法创建Schedule,通过Schedule、ScheduleOne方法添加延迟调度任务,通过CancelTask方法取消任务,通过Shutdown停止延迟任务
type Schedule struct {//任务堆,按时间排序taskHeap taskHeaptaskMap  map[TaskId]*Task//调度器是否运行中running atomic.Bool//下一个任务idnextTaskId atomic.Uint32//任务运行池pool *ants.Pool//添加任务ChanaddTaskChan chan *Task//删除任务ChanstopTaskChan chan struct{}//取消任务ChancancelTaskChan chan TaskId
}// NewSchedule 构建一个Schedule
// workerNum 工作的协程数量,options ants协程池的配置,除了WithMaxBlockingTasks不能配置,别的都可以,具体参考:https://github.com/panjf2000/ants
func NewSchedule(workerNum int, options ...ants.Option) (*Schedule, error) {//延迟任务的最大任务数量必须不限制options = append(options, ants.WithMaxBlockingTasks(0))//创建一个协程池pool, err := ants.NewPool(workerNum)if err != nil {return nil, err}//创建一个延迟调度结构体s := &Schedule{taskHeap:       make(taskHeap, 0),taskMap:        make(map[TaskId]*Task),running:        atomic.Bool{},nextTaskId:     atomic.Uint32{},pool:           pool,addTaskChan:    make(chan *Task),stopTaskChan:   make(chan struct{}),cancelTaskChan: make(chan TaskId),}//启动调度 会开启一个协程去将即将要调度的任务添加到协程池中运行s.start()return s, nil
}// ScheduleOne 添加延迟调度任务,只调度一次
// job 执行的方法 duration 周期间隔,如果是负数立马执行,如果是负数立马且只执行一次
func (s *Schedule) ScheduleOne(job func(), duration time.Duration) (uint32, error) {return s.doSchedule(job, duration, true)
}// Schedule 添加延迟调度任务,重复调度
// job 执行的方法 duration 周期间隔,如果是负数立马且只执行一次
func (s *Schedule) Schedule(job func(), duration time.Duration) (uint32, error) {return s.doSchedule(job, duration, false)
}// doSchedule 添加延迟调度任务的具体实现
func (s *Schedule) doSchedule(job func(), duration time.Duration, onlyOne bool) (uint32, error) {if s.running.Load() {//如果是负数 只执行一次if duration <= 0 {onlyOne = true}nextTaskId := s.getNextTaskId()task := new(Task)task.job = jobtask.executeTime = time.Now().Add(duration)task.onlyOne = onlyOnetask.duration = durationtask.id = TaskId(nextTaskId)task.index = 0s.addTaskChan <- taskreturn uint32(task.id), nil} else {return invalidTaskId, ErrScheduleShutdown}
}// CancelTask 取消延迟调度任务
// taskId 任务id
func (s *Schedule) CancelTask(taskId uint32) {if s.running.Load() {if taskId != invalidTaskId {s.cancelTaskChan <- TaskId(taskId)}}
}// Shutdown 结束延迟任务调度
func (s *Schedule) Shutdown() {//通过cas设值if s.running.CompareAndSwap(true, false) {s.stopTaskChan <- struct{}{}}
}// IsShutdown 延迟任务调度是否关闭
func (s *Schedule) IsShutdown() bool {return !s.running.Load()
}// start 启动延迟任务调度
func (s *Schedule) start() {s.running.Store(true)go func() {for {now := time.Now()var timer *time.Timer//如果没有任务提交,睡眠等待任务if s.taskHeap.Len() == 0 {timer = time.NewTimer(math.MaxUint16 * time.Hour)} else {task := s.taskHeap.Peek()//设置执行间隔timer = time.NewTimer(task.executeTime.Sub(now))}select {case <-timer.C://到达第一个任务执行时间task := heap.Pop(&s.taskHeap).(*Task)//提交到线程池执行,返回的error不需要处理,因为任务池是无限大_ = s.pool.Submit(task.job)//单次执行则删除,多次执行,则更新if task.onlyOne {s.removeTask(false, task)} else {s.updateTask(task)}case taskId := <-s.cancelTaskChan:timer.Stop()//如果取消的任务id在待执行任务列表中,则删除任务if task, ok := s.taskMap[taskId]; ok {s.removeTask(true, task)}case task := <-s.addTaskChan:timer.Stop()//添加任务s.addTask(task)case <-s.stopTaskChan:timer.Stop()//关闭资源s.close()return}}}()
}// updateTask 更新延迟调度任务
func (s *Schedule) updateTask(executedTask *Task) {//拷贝 并设置新的执行时间和IDtask := *executedTasktask.executeTime = time.Now().Add(task.duration)//把已执行的任务删除s.removeTask(false, executedTask)//添加新的任务s.addTask(&task)
}// removeTask 移除任务
func (s *Schedule) removeTask(removeHeap bool, task *Task) {//从Map和堆中delete(s.taskMap, task.id)if removeHeap {heap.Remove(&s.taskHeap, task.index)}
}// addTask 添加任务
func (s *Schedule) addTask(task *Task) {heap.Push(&s.taskHeap, task)s.taskMap[task.id] = task
}// getNextTaskId 获取下一个任务id
func (s *Schedule) getNextTaskId() uint32 {taskId := s.nextTaskId.Add(1)if taskId == invalidTaskId {taskId = s.nextTaskId.Add(1)}return taskId
}// close 关闭Schedule资源和协程池的资源
func (s *Schedule) close() {//关闭所有资源并设置为 nil help gcs.taskHeap = nils.taskMap = nils.pool.Release()s.pool = nilclose(s.addTaskChan)close(s.cancelTaskChan)close(s.stopTaskChan)s.addTaskChan = nils.cancelTaskChan = nils.stopTaskChan = nil
}// Task 调度任务结构体,是一个调度任务的实体信息
type Task struct {// 任务idid TaskId// 执行的时间,每次执行完,如果重复调度就重新计算executeTime time.Time// 周期间隔duration time.Duration// 执行的任务job func()// 是否只执行一次onlyOne bool//所在堆数组的下标位置index int
}// 任务的堆,使用队只需要在添加的时候进行排序,堆顶是最先要执行的任务
type taskHeap []*Task// 下面都是堆接口的实现func (t *taskHeap) Len() int {return len(*t)
}
func (t *taskHeap) Less(i, j int) bool {return (*t)[i].executeTime.Before((*t)[j].executeTime)
}func (t *taskHeap) Swap(i, j int) {(*t)[i], (*t)[j] = (*t)[j], (*t)[i](*t)[i].index = i(*t)[j].index = j
}func (t *taskHeap) Push(x interface{}) {*t = append(*t, x.(*Task))
}func (t *taskHeap) Pop() interface{} {old := *tn := len(old)x := old[n-1]old[n-1] = nil*t = old[:n-1]return x
}// Peek 查看堆顶元素,非堆接口的实现
func (t *taskHeap) Peek() *Task {return (*t)[0]
}

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

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

相关文章

杰发科技AC7801——滴答定时器获取时间戳

1. 滴答定时器 杰发科技7801内部有一个滴答定时器&#xff0c;该定时器是M0核自带的&#xff0c;因此可以直接用该定时器来获取时间戳。 同样&#xff0c;7803也可以使用该方式获取时间戳。 2. 滴答定时器原理 SysTick是一个24位的递减计数器&#xff0c;它从预设的重装载值…

湖仓一体概述

湖仓一体之前&#xff0c;数据分析经历了数据库、数据仓库和数据湖分析三个时代。 首先是数据库&#xff0c;它是一个最基础的概念&#xff0c;主要负责联机事务处理&#xff0c;也提供基本的数据分析能力。 随着数据量的增长&#xff0c;出现了数据仓库&#xff0c;它存储的是…

第十五届蓝桥杯单片机组4T模拟赛三(第二套)

本套试题在4T平台中的名字为第15届蓝桥杯单片机组模拟考试三&#xff0c;不知道哪套是4T的模拟赛&#xff0c;所以两套都敲一遍练练手感。 为了代码呈现美观&#xff0c;本文章前面的各个模块在main函数中的处理函数均未添加退出处理&#xff0c;在最后给出的完整代码中体现。 …

CT技术变迁史——CT是如何诞生的?

第一代CT(平移-旋转) X线球管为固定阳极,发射X线为直线笔形束,一个探测器,采用直线和旋转扫描相结合,即直线扫描后,旋转1次,再行直线扫描,旋转180完成一层面扫描,扫描时间3~6分钟。矩阵象素256256或320320。仅用于颅脑检查。 第二代CT (平移-旋转) 与第一代无质…

Android APK组成编译打包流程详解

Android APK&#xff08;Android Package&#xff09;是 Android 应用的安装包文件&#xff0c;其组成和打包流程涉及多个步骤和文件结构。以下是详细的说明&#xff1a; 一、APK 的组成 APK 是一个 ZIP 格式的压缩包&#xff0c;包含应用运行所需的所有文件。解压后主要包含以…

基于Rook的Ceph云原生存储部署与实践指南(上)

#作者&#xff1a;任少近 文章目录 1 Ceph环境准备2 rook部署ceph群集2.1 Rook 帮助地址2.2 安装ceph2.3 获取csi镜像2.4 Master参加到osd2.5 设置默认存储 3 Rook部署云原生RBD块存储3.1 部署storageclass资源3.2 部署WordPress使用RBD3.3 WordPress访问 4 Rook部署云原生RGW…

DeepSeek R1/V3满血版——在线体验与API调用

前言&#xff1a;在人工智能的大模型发展进程中&#xff0c;每一次新模型的亮相都宛如一颗投入湖面的石子&#xff0c;激起层层波澜。如今&#xff0c;DeepSeek R1/V3 满血版强势登场&#xff0c;为大模型应用领域带来了全新的活力与变革。 本文不但介绍在线体验 DeepSeek R1/…

Spring Data JPA 中的分页实现:从 BasePage 到 Pageable

文章目录 Spring Data JPA 中的分页实现&#xff1a;从 BasePage 到 Pageable背景&#xff1a;为什么需要分页&#xff1f;认识 BasePage 类深入 toPageable() 方法1. 处理页码和页面大小2. 处理排序方向3. 处理排序字段4. 生成 Pageable 对象 实战&#xff1a;如何使用 BasePa…

Android Studio 新版本Gradle发布本地Maven仓库示例

发布代码到JitPack示例&#xff1a;https://blog.csdn.net/loutengyuan/article/details/145938967 以下是基于 Android Studio 24.2.2&#xff08;Gradle 8.10.2 AGP 8.8.0 JDK17&#xff09; 的本地 Maven 仓库发布示例&#xff0c;包含aar和jar的不同配置&#xff1a; 1.…

python量化交易——金融数据管理最佳实践——qteasy创建本地数据源

文章目录 qteasy金融历史数据管理总体介绍本地数据源——DataSource对象默认数据源查看数据表查看数据源的整体信息最重要的数据表其他的数据表 从数据表中获取数据向数据表中添加数据删除数据表 —— 请尽量小心&#xff0c;删除后无法恢复&#xff01;&#xff01;总结 qteas…

LDR6020 PD3.1 协议芯片在特定设备中的应用

在电子设备互联互通的时代&#xff0c;芯片技术成为提升设备性能与功能的关键驱动力。LDR6020 PD3.1 协议芯片以其出色的性能&#xff0c;在 TYPE-C 台式显示器 / 便携显示器、一拖二快充线以及手机电脑转接器等设备中展现出独特价值&#xff0c;为用户带来更便捷、高效的使用体…

PDF处理控件Aspose.PDF教程:使用 Python 将 PDF 转换为 TIFF

TIFF文件是高质量图像的首选。它们广泛用于印刷、存档和图形设计。企业通常需要转换PDF文档以获得更好的兼容性。了解如何以编程方式执行此转换可以节省时间和资源。在这篇教程中&#xff0c;我们将探讨如何使用 Python 将 PDF 转换为 TIFF。 本文涵盖以下主题&#xff1a; P…

服务器IPMI用户名、密码批量检查

背景 大规模服务器部署的时候&#xff0c;少不了较多的网管和监测平台&#xff0c;这些平台会去监控服务器的性能、硬件等指标参数&#xff0c;为了便于管理和控制&#xff0c;则需要给服务器IPMI带外管理添加较多的用户&#xff0c;这就需要对较多的服务器检查所对应的IPMI用…

< 自用文儿 > Gobuster 暴力扫描工具与 SecLists 安全测试词表集合

Ethice 道德问题 GFW 的保护下&#xff0c;很多的设备操作系统是停留在更老的版本&#xff0c;应用软件也是&#xff0c;因此很多的漏洞没有被修复。通讯没有使用加密&#xff0c;例如网页没有使用 HTTPS 网站很多。几乎是半裸的在网络上等着被食。 不做恶是下限。 环境&…

【Cadence射频仿真学习笔记】2.4GHz低噪放LNA仿真设计

课程分为3个部分&#xff0c; 一、LNA结构与噪声优化方法 噪声优化的方法是&#xff1a;限定功耗的噪声和功率同时匹配噪声匹配和功率匹配一般不会同时达到&#xff0c; 对于PCSNIM结构的噪声分析&#xff0c;我们只需要了解与哪些参数有关优化思路是&#xff1a;1.信号源阻抗…

【洛谷入门赛】B4042 顺序结构 202410 场

题意 给你一个变量 a a a&#xff1a;小 Y 会让 a a a 先加 5 5 5 再把它们的和乘 3 3 3 最后输出&#xff1b;小 L 会让 a a a 先乘 3 3 3 再加 5 5 5 最后输出。 要求出小 Y 和小 L 分别会输出什么东西。 思路 这道题按照题目意思模拟就可以了&#xff0c;重点是考…

【Azure 架构师学习笔记】- Azure Databricks (13) -- 搭建Medallion Architecture part 1

本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Databricks】系列。 接上文 【Azure 架构师学习笔记】- Azure Databricks (12) – Medallion Architecture简介 前言 上文已经介绍了关于Medallion的知识&#xff0c;本文开始用ADB 来实现&#xff0c; 但是基于内容较…

社交APP如何打造高粘性兴趣社群

想要打造一款成功的社交 APP 兴趣社群&#xff0c;关键在于充分激发用户的主动分享意愿&#xff0c;同时构建起深度互动机制。与其在一开始就将大量资源投入到广告宣传中&#xff0c;倒不如把精力集中在深度挖掘和精心维护首批核心用户上。例如&#xff0c;可以尝试设计在线测试…

【操作系统】同步与互斥

同步与互斥 一、同步与互斥的概念1.1 同步与异步1.2 进程互斥 二、进程互斥的实现2.1 软件实现2.1.1 单标志法2.1.2 双标志先检查法2.1.3 双标志后检查法2.1.4 Peterson法 2.2 硬件实现2.2.1 中断指令2.2.2 TestAndSet指令2.2.3 Swap指令 三、互斥锁四、信号量机制4.1 整型信号…

性能附录:如何计算并发用户数(摘自高楼老师《性能30讲》)

高楼老师《性能30讲》: 性能测试实战30讲-极客时间 感兴趣的同学可以去读一下&#xff0c;个人感觉写的非常好 目录 什么是并发? 在线用户数、并发用户数怎么计算 总结 什么是并发? 我们假设上图中的这些小人是严格按照这个逻辑到达系统的&#xff0c;那显然&#xff0c;…