JAVA基础-线程(Thread)、多线程(Multi-threaded)

Java多线程基础-4:详解Thread类及其基本用法 万字详解Java多线程编程类Thread及其基本用法。 阅读详情

1、知识铺垫

        要想了解什么是线程,首先要搞明白线程与进程的区别,并行与并发的区别

1.1 线程与进程

        进程:是指⼀个内存中运⾏的应⽤程序,每个进程都有⼀个独⽴的内存空间,⼀个应⽤程序可以同时运⾏多个进程;进程也是程序的⼀次执⾏过程,是系统运⾏程序的基本单位;系统运⾏⼀个程序即是 ⼀个进程从创建、运⾏到消亡的过程。
        线程:线程是进程中的⼀个执⾏单元,负责当前进程中程序的执⾏,⼀个进程中⾄少有⼀个线程。⼀个进程中是可以有多个线程的,这个应⽤程序也可以称之为多线程程序。
        简⽽⾔之:⼀个程序运⾏后⾄少有⼀个进程,⼀个进程中可以包含多个线程

1.2 并行与并发

并发:指两个或多个事件在同⼀个时间段内发⽣。
并⾏:指两个或多个事件在同⼀时刻发⽣(同时发⽣)。

        在操作系统中,安装了多个程序,并发指的是在⼀段时间内宏观上有多个程序同时运⾏,这在单 CPU 系统中,每⼀时刻只能有⼀道程序执⾏,即微观上这些程序是分时的交替运⾏,只不过是给⼈的感觉是同时运 ⾏,那是因为分时交替运⾏的时间是⾮常短的。

        ⽽在多个 CPU 系统中,则这些可以并发执⾏的程序便可以分配到多个处理器上( CPU ),实现多任务并⾏ 执⾏,即利⽤每个处理器来处理⼀个可以并发执⾏的程序,这样多个程序便可以同时执⾏。⽬前电脑市场 上说的多核 CPU ,便是多核处理器,核 越多,并⾏处理的程序越多,能⼤⼤的提⾼电脑运⾏的效率。

注意:单核处理器的计算机肯定是不能并⾏的处理多个任务的,只能是多个任务在单个 CPU 上并发运 ⾏。同理 , 线程也是⼀样的,从宏观⻆度上理解线程是并⾏运⾏的,但是从微观⻆度上分析却是串⾏ 运⾏的,即⼀个线程⼀个线程的去运⾏,当系统只有⼀个 CPU 时,线程会以某种顺序执⾏多个线程, 我们把这种情况称之为线程调度。

2、线程

2.1 创建线程的方式

  1. 继承Thread类并重写run()方法。
  2. 实现Runnable接口并重写run()方法。将Runnable实例作为Thread类的构造函数参数传递并启动线程。
  3. 实现Callable接口并重写call()方法。使用ExecutorService的submit()方法提交Callable任务,并通过Future对象获取返回值。
  4. 线程池创建

2.1.1 Runnable 和 Callable 的区别

Runnable 接口 run 方法无返回值,且无法捕获处理异常;

Callable 接口 call 方法有返回值,支持泛型, 可以获取异常信息

2.2 线程的状态 

NEW(新建)

RUNNABLE(运行)

BLOCKED(阻塞)

WAITING(等待)

TIME_WAITING(超时等待)

TERMINATED (终止)

2.3 线程的相关方法

  1. 线程等待(wait):会释放对象的锁(进入waiting)
  2. 线程睡眠(sleep):不会释放当前占有的锁(进入time-waiting)
  3. 线程让步(yield):与其他线程一起重新竞争CPU 时间片
  4. 线程中断(interrupt):线程在合适的时候中断
  5. Join 等待其他线程终止:则当前线程转为阻塞状态,会到另一个线程结束,当前线程再由阻塞状态变为就绪状态,等待 cpu 的宠幸
  6. .线程唤醒(notify)

2.3.1 wait()和 sleep()的区别

wait()sleep()
来自的类Object 类Thread 类
锁的释放在等待的过程中会释放锁在等待的过程中不会释放锁
使用范围必须在同步代码块中使用可以在任何地方使用

2.3.2 run()与start()方法

run() 方法是线程的执行体,线程启动后会执行 run() 方法中的代码,当 run() 方法执行完毕后

start() 方法用于启动一个新线程,它会创建一个新的线程,并在新的线程中执行 run() 方法中的代码。在调用 start() 方法的时候,JVM 会为新的线程分配资源,并执行该线程中的 run() 方法。

2.4 ThreadLocal(token、localdate、traceid)

        线程级别的存储工具,是一个线程本地变量,为每一个线程都创建一个私有的变量,每个线程只能获取到自己的变量,从而避免了线程安全问题,是一个线程级别的哈希表,用于存储每个线程的变量。ThreadLocalMap 以 ThreadLocal 对象作为 key,以变量值作为 value,每个线程都可以通过 ThreadLocalMap 获取自己的变量

2.4.1 ThreadLocal使用场景

  1. 需要保存线程的上下文信息,例如 用户信息,通过token解析出来的用户id等
  2. 需要对线程的局部变量进行隔离,避免线程安全问题; LocalDate LocalDateTime
  3. 需要在跨类跨方法使用同一个变量,同时又不希望使用全局变量的情况;
  4. 需要避免传递参数的繁琐,例如在 Spring 框架中使用的事务管理。

2.4.2 ThreadLocal注意事项

每次使用后都要使用remove()删除数据

不不然会造成内存泄露,进而造成内存溢出

2.4.5 内存泄漏和内存溢出

  1. 内存泄漏:对象使用之后,并没有释放,内存一直被占用,业务代码频繁执行之后,大量这样的对象不被回收,造成可用的内存空间越来越少,最终造成内存溢出。通俗点讲就是 不用的垃圾没有丢掉.
  2. 内存溢出:当创建的对象的大小大于可用的内存容量大小。

3 、多线程

3.1 多线程的基本知识

        多线程是计算机多任务处理的一种方式,它允许单个程序中同时运行多个任务。在多线程模型中,每个线程代表执行流程中的一个独立的任务,它们可以并行处理以提高效率。

        在操作系统中,进程是资源分配的基本单位,而线程是程序执行的最小单位。一个进程可以包含多个线程,每个线程执行不同的任务。多线程的出现,使得程序可以同时执行多个任务,例如,一个文本编辑器可以在保存文件的同时继续接受用户的输入。

        多线程与单线程相比,最大的优势在于可以并行处理任务,提高资源利用率和程序响应速度。例如,一个网络服务器可以同时处理多个客户端请求,而不是一次处理一个。

4、线程池

        线程池(ThreadPool)是一种基于池化思想管理和使用线程的机制:它是将多个线程预先存储在一个“池子”内,当有任务出现时可以避免重新创建和销毁线程所带来性能开销,只需要从“池子”内取出相应的线程执行对应的任务即可

4.1 线程池的工作原理

当一个任务提交至线程池之后,

1. 线程池首先判断核心线程池里的线程是否已经满了。如果不是,则创建一个新的工作线程来执行任务。否则进入 2.

2. 判断工作队列是否已经满了,倘若还没有满,将任务放入队列。否则进入 3.

3. 判断线程池里的线程是否都在执行任务。如果不是,则创建一个新的工作线程来执行。

如果线程池满了,则交给饱和策略来处理任务。

4.1.2 线程池主要优点

  • 降低资源消耗(复用线程,减少线程频繁新建、销毁等带来的开销)
  • 提高响应速度
  • 提高线程的可管理性

4.1.2 阿里巴巴不推荐使用JDK自带线程池的原因

        同时,阿里巴巴在其《Java开发手册》中也强制规定:线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。

阿里巴巴开发手册为什么禁止使用 Executors 去创建线程池,原因就是 newFixedThreadPool() 和 newSingleThreadExecutor()两个方法允许请求的最大队列长度是 Integer.MAX_VALUE ,可能会出现任务堆积,出现OOM。newCachedThreadPool()允许创建的线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,导致发生OOM。它建议使用ThreadPoolExecutor方式去创建线程池,通过上面的分析我们也知道了其实Executors 三种创建线程池的方式最终就是通过ThreadPoolExecutor来创建的,只不过有些参数我们无法控制,如果通过ThreadPoolExecutor的构造器去创建,我们就可以根据实际需求控制线程池需要的任何参数,避免发生OOM异常。

4.2 使用线程池-线程池的创建方式

线程池的创建方法总共有 7 种,但总体来说可分为 2 类:

通过 ThreadPoolExecutor 创建的线程池
通过 Executors 创建的线程池

线程池的创建方式总共包含以下 7 种(其中 6 种是通过 Executors 创建的,1 种是通过 ThreadPoolExecutor 创建的):

  1. Executors.newFixedThreadPool():创建一个固定大小的线程池,可控制并发的线程数,超出的线程会在队列中等待;
  2. Executors.newCachedThreadPool():创建一个可缓存的线程池,若线程数超过处理所需,缓存一段时间后会回收多余的线程,若线程数不够,则新建线程;
  3. Executors.newScheduledThreadPool():创建一个可以执行延迟任务的线程池;
  4. Executors.newSingleThreadExecutor():创建单个线程数的线程池,它可以保证先进先出的执行顺序;
  5. Executors.newSingleThreadScheduledExecutor():创建一个单线程的可以执行延迟任务的线程池;
  6. Executors.newWorkStealingPool():创建一个抢占式执行的线程池(任务执行顺序不确定)JDK 1.8 添加
  7. ThreadPoolExecutor:最原始的创建线程池的方式,它包含了 7 个参数可供设置

        单线程池的意义: 虽然 newSingleThreadExecutor 和 newSingleThreadScheduledExecutor 是单线程池,但提供了工作队列,生命周期管理,工作线程维护等功能。

4.3 线程池的参数

参数代表的含义如下:

  • corePoolSize:核心线程数,线程池中始终存活的线程数。
  • maximumPoolSize:最大线程数,线程池中允许的最大线程数,当线程池的任务队列满了之后可以创建的最大线程数。
  • keepAliveTime:最大线程数可以存活的时间,当线程中没有任务执行时,最大线程就会销毁一部分,最终保持核心线程数量的线程。

unit:单位是和参数 3 存活时间配合使用的,合在一起用于设定线程的存活时间。参数 keepAliveTime 的时间单位有以下 7 种可选:

  1. TimeUnit.DAYS:天
  2. TimeUnit.HOURS:小时
  3. TimeUnit.MINUTES:分
  4. TimeUnit.SECONDS:秒
  5. TimeUnit.MILLISECONDS:毫秒
  6. TimeUnit.MICROSECONDS:微妙
  7. TimeUnit.NANOSECONDS:纳秒
  • workQueue:一个阻塞队列,用来存储线程池等待执行的任务,均为线程安全。

        它一般分为直接提交队列、有界任务队列、无界任务队列、优先任务队列几种,包含以下 7 种类型:

  1. ArrayBlockingQueue:一个由数组结构组成的有界阻塞队列。
  2. LinkedBlockingQueue:一个由链表结构组成的有界阻塞队列。
  3. SynchronousQueue:一个不存储元素的阻塞队列,即直接提交给线程不保持它们。
  4. PriorityBlockingQueue:一个支持优先级排序的无界阻塞队列。
  5. DelayQueue:一个使用优先级队列实现的无界阻塞队列,只有在延迟期满时才能从中提取元素
  6. LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。与SynchronousQueue类似,还含有非阻塞方法。
  7. LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。

        较常用的是 LinkedBlockingQueue 和 Synchronous,线程池的排队策略与 BlockingQueue 有关

threadFactory:线程工厂,主要用来创建线程。

handler:拒绝策略,拒绝处理任务时的策略,系统提供了 4 种可选:

  1. AbortPolicy中止策略(默认):拒绝并抛出异常。
  2. CallerRunsPolicy调用者运行策略:使用当前调用的线程来执行此任务。
  3. DiscardOldestPolicy丢弃最旧任务策略:抛弃队列头部(最旧)的一个任务,并执行当前任务。
  4. DiscardPolicy丢弃策略:忽略并抛弃当前任务。

 4.4 线程池的状态

1. 初始状态:线程池被创建时,里面并没有任何线程。此时线程池的状态为初始状态。

2. 运行状态:当向线程池中提交任务后,线程池中的线程开始执行任务,此时线程池的状态为运行状态。

3. 阻塞状态:当线程池中的任务队列已满,无法再接受新的任务时,线程池会进入阻塞状态,等待任务队列中的任务被执行完毕后再接受新的任务。

4. 关闭状态:当调用线程池的shutdown()方法时,线程池会进入关闭状态,此时线程池不再接受新的任务,但会执行任务队列中的任务。

5. 停止状态:当调用线程池的shutdownNow()方法时,线程池会进入停止状态,此时线程池不再接受新的任务,并且会中断正在执行的任务。

6. 终止状态:当线程池中所有的任务都执行完毕后,线程池会进入终止状态,此时线程池中不再有任何线程。

4.4.1 shutdownNow与shutdown的区别

1、shutdownNow 首先将线程池的状态设置为 STOP,然后尝试停止所有的正在执行和未执行任务的线程,并返回等待执行任务的列表;

2、shutdown 只是将线程池的状态设置为 SHUTDOWN 状态,然后中断所有没有正在执行任务的线程,继续执行正在执行的任务,直到任务结束.

5 、线程死锁 

5.1 死锁

        线程死锁是指由于两个或者多个线程互相持有对方所需要的资源,导致这些线程处于等待状态,无法继续执行

5.1.1 死锁的产生的条件(4者缺一不可)

  1. 互斥条件:一个资源一次只能被一个线程持有,如果其他线程想要获取该资源,就必须等待该线程释放该资源。
  2. 保持条件:一个线程请求资源时,如果已经持有了其他资源,就可以保持对这些资源的控制,直到满足所有资源的要求才释放
  3. 不剥夺条件:已经分配的资源不能被其他线程剥夺,只能由持有资源的线程释放
  4. 环路等待条件:个线程形成一种循环等待的关系,每个线程都在等待其他线程所持有的资源,从而导致死锁的产生。

5.1.2 如何避免死锁

避免死锁

  1. 尽量避免使用多个锁
  2. 减少锁的粒度:确保同步代码块的执行时间尽可能短,这样可以减少线程等待时间,
  3. 使用尝试锁:通过 ReentrantLock.tryLock() 方法可以尝试获取锁
  4. 避免嵌套锁

6、Synchronized同步锁

        会使用对象的内置锁(也称为监视器锁)来实现同步,每个对象都有一把内置锁,当一个线程访问一个同步代码块时,它会尝试获取这个锁,如果锁被其他线程持有,则该线程将被阻塞,直到锁被释放

  1. 互斥性(一个线程拿锁,其他线程不能拿锁)
  2. 可重入性(同一个线程可以多次获取同步锁)
  3. 独占性(一个线程获得了对象的锁,则其他线程必须等待该线程释放锁之后才能获取锁。)
  4. 缺点:非公平锁

6.2 synchronized静态方法和非静态方法的区别

  1. 当 synchronized 修饰非静态方法时,它实际上是对调用该方法的对象实例进行加锁。这意味着如果有多个线程尝试访问同一个对象实例的不同 synchronized 非静态方法,它们将被串行执行,因为这些线程需要获取同一个对象锁。
  2. synchronized 修饰静态方法时:它锁定的是类的Class对象,这意味着无论哪个线程访问该类的任何静态同步方法,都需要获取这个类的锁。因此,即使是不同的对象实例,只要它们调用的是同一个类的静态同步方法,这些调用也必须排队执行。

6.3 Synchronized与lock的区别

区别

Synchronized与lock

Lock(reentrantlock)

类型

关键字

接口

加锁方式

隐藏的加锁

显示的加锁

作用域

作用于方法上面

只能用于方法块上面

底层

对象内置锁

AQS(AbstractQueuedSynchronizer 抽象队列同步器)

锁类型

非公平锁

可选择非公平或公平锁

6.4 锁的升级 

6.4.1 基本概念

无锁 (用户)-> 偏向锁(用户) -> 轻量级锁(用户端) -> 重量级锁

        这是Java中针对synchronized锁的一种优化策略,它描述了锁状态可能经历的四个阶段,但并不是所有Java虚拟机都实现了这四个阶段,特别是偏向锁和轻量级锁的实现可能因JVM版本而异。

        对象刚创建是无锁状态,当第一个线程访问同步代码块时,升级为偏向锁,当第二个线程进来的时候,第二个线程会其实就是自旋锁,等待第一个线程释放锁,多线程压力比较大的时候用重量级锁(互斥锁)

6.4.2 锁升级过程

a. 无锁状态

对象刚创建时,并没有锁的介入,这时处于无锁状态。

b. 偏向锁(Biased Locking)

只需要用一个CAS操作和简单地判断比较,就可以让一个线程持续地拥有一个锁。

c. 轻量级锁

就像偏向锁的前提,是同步代码块在大多数情况下只有同一个线程访问的时候。

而轻量级锁的前提则是,线程在同步代码块里面的操作非常快,获取锁之后,很快就结束操作,然后将锁释放出来。

d. 重量级锁

相比起轻量级锁,再膨胀的锁,一般称之为重量级锁,因为是依赖于每个对象内部都有的monitor锁来实现的,而monitor又依赖于操作系统的MutexLock(互斥锁)来实现,所以一般重量级锁也叫互斥锁

7、JUC包

        JUC是java.util.concurrent包的简称,用于处理并发编程的工具包

同步工具:

  1. CountDownLatch(倒计时锁存器)、CyclicBarrier(循环屏障)、StampedLock(信号量)

并发集合:

  1. CurrentHashMap、CopyOnWriteLock、BlockingQueue

原子操作(cas原理):

  1. AtomicInteger、AtomicLong

锁:

  1. synchronized、ReentrantLock(重入锁)、ReentrantReadWriteLock(重入读写锁)、StampedLock(乐观读写锁)
JAVA多线程详解(超详细) 程序:开发写的代码称之为程序。程序就是一堆代码,一组数据和指令集,是一个静态的概念。进程(Process):将程序运行起来,我们称之为进程。进程是执行程序的一次执行过程,它是动态的概念。进程存在生命周期,也就是说程序随着程序的终止而销毁。进程之间是通过TCP/IP端口实现交互的。线程(Thread):线程是进程中的实际运作的单位,是进程的一条流水线,是程序的实际执行者,是最小的执行单位。通常在一个进程中可以包含若干个线程,当然一个进程中至少有一个线程。线程是CPU调度和执行的最小单位。注意。 阅读详情

相关推荐

Java创建线程的七种方法,全网最全面总结~

属于基础的面试问题,一定要能够回答全哦~

CYK_byte的博客 2万+

Java基础核心技术:多线程(day16-day17)

本套Java视频完全针对初级学员,课堂实录,自发布以来,好评如潮!Java视频中注重与学生互动,讲授幽默诙谐、细致入微,覆盖Java基础所有核心知识点,同类Java视频中也是代码量大、案例多、实战性强的。同时,本Java视频教程注重技术原理剖析,深入JDK源码,辅以代码实战贯穿始终,用实践驱动理论,并辅以必要的代码练习。

Datawhale~数据挖掘实践之序列问题处理~天池·资金流入流出预测-挑战Baseline~Day01~数据探索与分析

写在前面✍ 本系列笔记基于天池平台上“资金流入流出预测-挑战Baseline”学习赛,记录如何完整的打一次数据挖掘类比赛。同时,该比赛属于序列建模问题,希望学习完成这个任务,可以对序列问题的处理有一定的独立思考能力和实践操作能力,可以将所学理论,用编码的形式和实际的问题得到深入。 第一篇,EDA Content: 初步了解赛题及数据 1.1 任务 1.2 用户基本信息数据 1.3 用户申购赎回数据 1.4 收益率表 1.5 银行间拆借利率表 1.6 提交格式 1.7 评分指标 EDA 1 初.

小卜妞的博客 2358

JAVA线程

虽然我们可以理解同步代码块和同步方法的锁对象问题,但是我们并没有直接看到在哪里加上了锁,在哪里释放了锁,为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock,Lock是接口不能直接实例化,这里采用它的实现类ReentrantLock来实例化。

互联网底层民工的博客 1万+

esxi8.0.3如何添加USB外置硬盘

本文介绍了在ESXi系统中配置外置USB硬盘作为数据存储的完整步骤:1)通过SSH禁用USB仲裁服务并关闭自启;2)识别已连接的USB硬盘设备路径;3)使用partedUtil创建GPT分区表并计算扇区范围;4)设置VMFS6分区并格式化。关键命令包括停止usbarbitrator服务、partedUtil分区操作以及vmkfstools格式化命令。整个过程需通过SSH执行,最终将USB硬盘配置为名为"USB_Datastore"的VMFS6存储设备。

qq_41683719的博客 1545

【Java】解决Java报错:InterruptedException in Multi-threaded Applications

是Java中常见的检查型异常,在多线程应用程序中尤其容易发生。本文详细介绍了其产生原因,并提供了多种解决方案,包括正确处理、合理使用中断机制、使用高层次的并发工具以及设计可中断的任务。通过遵循最佳实践,开发者可以有效地避免和处理这种异常,提高代码的健壮性和可靠性。

Easonmax的博客 1415

SOLIDWORKS2024安装卡顿?Edge WebView2 Runtime冲突的排查与修复

本文针对SOLIDWORKS 2024安装时setup.exe无响应或卡死的常见问题,深入剖析了其根本原因在于Microsoft Edge WebView2 Runtime的版本冲突或组件损坏。文章提供了三种经过验证的解决方案:一是通过运行安装包内swwi\data目录下的setup.exe直接绕过图形界面;二是彻底卸载并重装官方Edge WebView2 Runtime组件;三是进行系统级修复与排查。旨在帮助用户快速定位并解决安装障碍,顺利完成软件部署。

4k5l6j7h8的博客 289

多线程Multi-Thread 基础

线程概念   线程就是程序中单独顺序的流控制。   线程本身不能运行,它只能用于程序中。   说明:线程是程序内的顺序控制流,只能使用分配给程序的资源和环境。   进程   进程:执行中的程序。   程序是静态的概念,进程是动态的概念。   一个进程可以包含一个或多个线程。   一个进程至少要包含一个线程。   线程与进程的区别   多个进程

红豆和绿豆的博客 375

Unity VR 零基础开发之 Pico4 MR

2、弹出弹窗后,点击Android选项,然后再点击Switch Platform按钮切换成安卓平台。3、切换完成后Android选项后面会显示unity图标。

十画的博客 5097

《Unity DOTS之ECS从入门到不香》(1)基本概念

文章目录一、什么是DOTS?二、什么是ECS?三、Hello World 一、什么是DOTS? Data Oriented Tech Stack(DOTS)是unity推出的多线程面向数据的技术堆栈 。它是一套高性能解决方案,包含三个部分: 1.ECS:ECS是一种有别于面向对象的编程模式,是面向CPU Cache友好的编程模式。要求代码都要按照 实体+组件+系统 的框架构建。官方链接 2.JobSystem:JobSystem是unity推出的一套先进的多线程任务管理系统,结合ECS可以获得最佳性能。当然

Cxihu田树东的游戏开发博客 2732

MultiThreadDownLoad多线程下载

前言: 两种创建线程的方式: 第一种方式:使用Runnable接口创建线程。 第二种方式:直接继承Thread类创建对象使用Runnable接口创建线程。      直接继承Thread类创建对象:(1)定义线程类(2)创建线程类对象(3)启动线程: 线程类对象.start(); 用Runnanble 创建线程的步骤:1.定义一个Runnable接口类。2.在

水无痕伊人恋 1042

[Python] 为什么你的脚本明明没报错,却什么也没发生?

Python脚本运行后没报错却没结果?这是许多开发者遇到的棘手问题。文章分析了六种常见原因:代码未进入目标逻辑分支、输出路径错误、中间数据为空、异常被吞掉、异步操作未完成、运行了错误脚本版本。建议通过"过程可视化"排查,如打印关键变量、检查工作目录、验证数据状态等。职场中更应关注结果验证而非单纯代码执行,确保脚本真正解决问题。建立结果验证意识是从"会写代码"到"稳定交付"的关键转变。

技术小甜甜:传播可落地技术,帮助个人和企业降低解决真实场景问题的成本 302

安全的多线程--Multi-Threaded with BlockingQueue

Article by :Jeff Langr Writing well-behaved, multi-threaded applications is one of the more challenging aspects of Java coding.One of the best ways to write multi-threaded applications is to take...

凌乱的碎片~ 298

黑猫带你学UFS协议第13篇:UFS初始化详解(Boot Operation)

本文详细解析了UFS设备的初始化过程,包括部分初始化、加载启动代码(可选)和初始化完成三个阶段。重点介绍了如何通过设备描述符和逻辑单元描述符配置引导特性,以及如何从UFS设备加载启动代码。内容适用于嵌入式硬件和存储领域的开发者。

黑猫奥利奥的博客 3555

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

使用多线程增加kafka消费能力

前提:本例适合那些没有顺序要求的消息主题。 kafka通过一系列优化,写入和读取速度能够达到数万条/秒。通过增加分区数量,能够通过部署多个消费者增加并行消费能力。但还是有很多情况下,某些业务的执行速度实在是太慢,这个时候我们就要用到多线程去消费,提高应用机器的利用率,而不是一味的给kafka增加压力。 使用Spring创建一个kafka消费者是非常简单的。我们选择的方式是继承kafka的Sh...

weixin_34343308的博客 1462

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

消费者多线程实现(十四)

消费者多线程实现 KafkaProducer 是线程安全的,然而 KafkaConsumer 却是非线程安全的。KafkaConsumer 中定义了一个 acquire() 方法,用来检测当前是否只有一个线程在操作,若有其他线程正在操作则会抛出 ConcurrentModifcationException 异常: java.util.ConcurrentModificationException: KafkaConsumer is not safe for multi-threaded a...

用键盘与世界交流 437

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

14_消费者多线程实现

KafkaProducer 是线程安全的,然而 KafkaConsumer 却是非线程安全的。KafkaConsumer 中定义了一个 acquire() 方法,用来检测当前是否只有一个线程在操作,若有其他线程正在操作则会抛出 ConcurrentModifcationException 异常: java.util.ConcurrentModificationException: KafkaConsumer is not safe for multi-threaded access. KafkaConsu

一个搬砖工人 679

kafka启动异常日志_使用多线程增加kafka消费能力

前提:本例适合那些没有顺序要求的消息主题。kafka通过一系列优化,写入和读取速度能够达到数万条/秒。通过增加分区数量,能够通过部署多个消费者增加并行消费能力。但还是有很多情况下,某些业务的执行速度实在是太慢,这个时候我们就要用到多线程去消费,提高应用机器的利用率,而不是一味的给kafka增加压力。使用Spring创建一个kafka消费者是非常简单的。我们选择的方式是继承kafka的Sh...

weixin_30780097的博客 346

从零手写C语言多线程HTTP服务器:深入理解网络编程与并发处理

网络编程是构建现代分布式系统的基石,其核心在于理解客户端与服务器之间通过套接字(Socket)进行通信的基本原理。HTTP协议作为应用层协议,定义了Web通信的请求-响应模型,而服务器并发处理能力则是支撑高可用服务的关键技术。通过实现一个多线程HTTP服务器,开发者可以深入掌握Socket编程、HTTP协议解析以及线程同步等核心概念,这对于构建高性能网络服务、理解Nginx等成熟服务器框架的底层机制具有重要价值。本文以C语言为例,结合**多线程**和**线程池**技术,详细解析如何构建一个能够处理并发连接的

weixin_30443813的博客 394

java多线程 消费者问题_java多线程经典问题(消费者生产者问题)

public class ConsumerProducer {public static void main(String[] args) {SyncStack ss = new SyncStack();Producer p = new Producer(ss);Consumer c = new Consumer(ss);new Thread(p).start();new Thread(c).st...

weixin_36041939的博客 137

Java - Multithreading zz

Java is amulti-threaded programming languagewhich means we can develop multi-threaded program using Java. A multi-threaded program contains two or more parts that can run concurrently and each part ...

weixin_30416497的博客 172

C++高性能网络爬虫实战:从架构设计到性能调优

网络爬虫作为数据采集的核心技术,其本质是通过自动化程序模拟浏览器行为,从互联网上抓取和解析结构化信息。其工作原理涉及HTTP协议通信、HTML解析、数据抽取及存储等环节。在工程实践中,高性能爬虫的技术价值在于能够高效、稳定地处理海量数据请求,满足实时监控、搜索引擎索引、市场分析等应用场景对数据时效性与规模的要求。针对Python等语言在高并发场景下的性能瓶颈,本文深入探讨了如何利用C++的多线程编程、内存精细控制及libcurl等库构建高吞吐、低延迟的爬虫系统,其中线程池管理与布隆过滤器是实现系统高性能与资

weixin_30553777的博客 347

kafka connect rebalance时herder大概率异常

如果因为some reason触发了task的rebalance,herder work可能发生异常,导致connect进程退出。 1. herder close sink worker时,不要走acquire流程; 2. herder close sink worker时,先等待一定时长(sleep或者加锁) 3. 在V3.0.0 版本,框架上做了改动,herder 只是置位close标记,不错其他的操作。

石权的博客 3579

Kafka 入门学习

1 初识KafKa 1.1基本概念 1.Producer:生产者,生产者负责创建消息,投递到Kafka中 2.Consumer:消费者,连接到KafKa上,并接收消息,进行处理。 3.Broker:独立的Kafka服务节点或者服务实例。 4.Topic: Kafka中消息以主题为单位进行归类。生产这将消息发送到特定的主题(每一个消息都需要指定主题),消费者负责订阅主题并进行消费。 5.Partition:主题是一个逻辑上的概念,他可以细分为多个分区。 同一主题下的不同分区包含的消息不同。分区在

1190

C++高性能日志系统实战:5分钟用spdlog告别凌乱printf调试

日志系统是软件开发中的基础设施,它通过系统性地记录程序运行状态、错误和关键信息,为问题定位和系统监控提供支持。其核心原理在于将日志记录与业务逻辑分离,采用异步I/O和格式化输出机制,平衡性能与可靠性。在技术价值上,一个设计良好的日志系统能显著提升调试效率、便于线上故障追溯,并支持性能监控。在C++开发中,面对多线程、高性能等应用场景,spdlog库以其极简设计和卓越性能成为热门选择。它通过异步日志器和接收器分离架构,结合环形缓冲区队列,实现了低延迟、高吞吐的日志记录,帮助开发者快速构建专业级日志解决方案。

weixin_34234721的博客 353
上一篇: JAVA的三大特性-封装、继承、多态
下一篇: Spring事务的底层原理
涵冰...
博客等级 码龄4年 2438粉丝 243原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

涵冰...

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值