目录

Life in Flow

知不知,尚矣;不知知,病矣。
不知不知,殆矣。

线程池

线程池  单个请求处理的时间很短,海量请求的情况下,频繁的创建线程,销毁线程所带来的系统开销是巨大的。 降低频繁创建、销毁线程的开销、线程的创建和销毁需要 JVM 进行大量的辅助操作。(内存的分配与回收、还会给垃圾回收器带来压力) “池”的概念可以很好的防止资源不足。过多线程会占用大量内存,导致OOM。 加快响应速度(复用池中的线程) 合理利用CPU和内存。 统一管理资源。 线程池适用的场景 服务器接受到大量请求时,使用线程池技术是非常适合的,它可以大大减少线程的创建和销毁次数,提高服务器的工作效率。 5个以上的线程就可以使用线程池来管理。 不使用线程池(海量任务) 线程的创建和销毁需要 JVM 进行大量的辅助操作。(内存的分配与回收、还会给垃圾回收器带来压力) 在Java语言中每创建一个线程直接对应操作系统中的一个线程。在操作系统中频繁创建、销毁大量线程会造成很大的系统开销。操作系统支持创建的线程数是有上限的。(线程数量无法与未知的任务数量一一对应) 无法作用于C10K场景,会引发OOM异常。 public class EveryTaskOneThread { publi....

并发工具类

CountDownLatch  创建 CountDownLatch 实例的时候需要传入线程数,await()操作进入等待状态,每个线程执行完毕调用 countDown(),计数器减一,当计数器为 0 的时候处于 WAITING 状态的线程会被唤醒。  应用场景:启动三个线程计算,需要每个线程的计算结果进行累加。 CountDownLatch import java.util.concurrent.CountDownLatch; public class CountDownLatchDemo { public static void main(String[] args) { CountDownLatch countDownLatch = new CountDownLatch(8); for (int i = 0; i < 8; i++) { int finalI = i; new Thread(()->{ try { Thread.sleep(finalI * 1000L); System.out.println(Thread.currentThread().getName....

原子类

原子类  原子是不可分割的最小单位,故原子类可以认为其操作都是不可分割。  一个操作是不可中断的,即便是在多线程情况下也可以保证。  java.uti.concurrent.aomic包下有很多具有原子特性的类。 原子类 VS 锁 粒度更细:原子变量可以把竞争范围缩小到变量级别,这是我们可以获得的最细粒度的情况,锁的粒度通常大于原子类。 效率更高:通常,使用原子类的效率会比使用锁的效率更高,除了高度竞争的情况下。 6类原子类纵览 基本类型原子类  以 AtomicInteger 为例,本质是对 Integer 的封装,提供原子的访问和更新操作,其本质是基于 CAS 技术。 AtomicInteger 常用方法 * get() 获取当前的值 * getAndSet() 获取当前的值,并设置新的值 * getAndIncrement() 获取当前的值,并自增 * getAndDecrement() 获取当前的值,并自减 * getAndAdd() 获取当前的值,并加上预期的值 * compareAndSet() 如果输入的数值等于预期值,则以原子方式将该值设置为输入值(update....

线程安全与程序性能

线程安全  当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那这个对象时线程安全的。----《并发编程实战》 主要是两个问题 数据争用:多个线程同时修改共享数据,会造成错误数据。(原子性) 竞争条件:操作顺序造成的问题,例如:读取发生在写入之前。(可见性、重排序) 线程安全带来的性能开销  运行速度、设计成本(增加编码的复杂度)、trade off 线程安全问题分类 运行结果错误:a++ 多线程下出现消失的请求现象 活跃性问题:死锁、活锁、饥饿 对象发布和初始化的时候的安全问题:由于顺序源于依然会造成错误,比如在写入之前就读取了。 * 发布:一个对象被声明为public,它就是被发布出去了,或者return 对象,或者方法传参 * 初始化 * 逸出: 1、方法返回了一个 private 对象(private 的本意是不让外部访问,这样就没人可以访问此对象了)。 2、还未完成初始化(构造函数完全执行完毕)就把对象提供给外界,比如: 在构造函数中为初....

线程的创建、启动、停止

线程的创建方式:继承 Thread  run()整个都被重写 任务与线程类高度耦合。 每次新建任务都需要创建独立的线程,如果使用 Runnable 则可以利用线程池,大大减少创建线程和销毁线程的开销。 Java 只允许单继承,影响扩展性。 public class MyThread extends Thread { @Override public void run() { System.out.println(Thread.currentThread().getName()); } public static void main(String[] args) { MyThread myThread = new MyThread(); myThread.setName("线程demo"); myThread.start(); } } 线程的创建方式:实现 Runnable  最终调用 target.run() 任务与线程类解耦 可扩展 解决资源开销(利用线程池) public class MyRunable implements Runnable,Serializable {....

并行的世界

并发简史  早期计算机(不包含操作系统),只能从头到尾执行一个程序,并且执行的程序能访问计算机中的所有资源。  操作系统的出现使得计算机每次能运行多个程序,并且不同程序都在单独的进程中运行:操作系统为各个独立执行的进程分配各种资源,包括内存、文件句柄以及安全证书等。计算机中加入操作系统来实现多个程序的同时执行,主要是基于以下原因: 资源利用率(同步等待造成的资源浪费) 公平性(通过时间分片实现用户和程序共享计算机资源) 便利性(多程序开发可以降低单个程序的开发的复杂度) 串行与并行的区别  好处:可以缩短整个流程的时间 串行(5):洗茶具 => 打水 => 烧水(同步等待) => 等水开 => 冲茶 并行(4):打水 => 烧水同时洗茶具 => 水开 => 冲茶 可怕的现实:摩尔定律的失效  摩尔定律:当价格不变时,集成电路上可容纳的元器件的数目,约每隔 18-24 个月便会增加一倍,性能也将提升一倍。这一定律揭示了信息技术进步的速度。 ​  然而,在 2004 年,Intel 的 4GHz 芯片宣布推迟到 2005 年,然后再 200....

基于Redis的sorted set实现排行榜功能

业务需求  排行榜功能是一个很普遍的需求。使用 Redis 中有序集合的特性来实现排行榜是又好又快的选择。 一般排行榜都是有实效性的,比如“用户积分榜”,游戏中活跃度排行榜,游戏装备排行榜等。 需求面临的问题 数据库设计复杂。 并发数较高。 数据要求实时性高。 Redis 相关 API 概述 封装 Redis 工具类 RedisService Service 层(RangingService 使用 Redis 工具类) import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.ZSetOperations; import org.springframework.stereotype.Service; import java.util.LinkedHashMap; import java.util.List; im....