分类 java 中的文章

阿里巴巴Java开发手册与代码规约插件P3C-PMD

P-3C Orion【猎户座反潜巡逻机】,阿里大概取p3c先进,监测,发现潜在问题的意思 前言 2017年的时,阿里官方首次公开阿里Java代码规范标准,发布阿里巴巴Java开发手册。 这套Java统一规范标准将有助于提高行业编码规范化水平,帮助行业人员提高开发质量和效率、大大降低代码维护成本。 目前已更迭了五个版本,2019年6月19日,阿里巴巴Java开发手册(华山版)》正式发布,该版本命名为华山版是因为最新版本手册集成了社区开发者集体智慧的结晶。 该开发手册阿里内部Java工程师所遵循的开发规范,涵盖编程规约、单元测试规约、异常日志规约、MySQL规约、工程规约、安全规约等,这是近万名阿里Java技术精英的经验总结,并经历了多次大规模一线实战检验及完善。这是阿里回馈给Java社区的一份礼物,希望能够帮助企业开发团队在Java开发上更高效、容错、有协作性,提高代码质量,降低项目维护成本。 虽然已经发布了开发手册,但是为了让开发者更加方便、快速的将规范推动并实行起来,阿里巴巴基于手册内容,研发了一套自动化的IDE检测插件(IDEA、Eclipse), 该插件在扫描代码后,将不符合《手册》的代码按Blocker/Critical/Major三个等级显示在下方,甚至在IDEA上,还基于检查机制提供了实时检测功能,编写代码的同时也能快速发现问题所在。另外对于历史代码,部分规则实现了批量一键修复的功能,提升代码质量,提高团队研发效能。 如何安装 eclipse安装 1.打开https://p3c.alibaba.com/plugin/eclipse/update 2.点击Zip File直接下载,下载完成后解压缩,将将【features】及【plugins】两个目录复制到eclipse安装目录下(eclipse.exe同级目录),重启eclipse idea安装 1.访问:https://plugins.jetbrains.com/plugin/10046-alibaba-java-coding-guidelines/versions 下载对应版本的安装包 2.依次点击【File】->【Settings】->【Plugins】->【install plugin from disk】然后点击确认 如何使用 1.首先现贴一段测试代码 public class Test { public static void main(String[] args) { String _name = "name"; System.out.println(_name.equals("name")); Long temp = 10l; if(temp ==10L) System.out.println("temp = 10"); else System.out.println("temp != 10"); HashMap<String,Integer> map = new HashMap<>(); } } 扫描后的结果: ……

阅读全文

阿里支付

[x]当面付-扫码支付快速接入(https://docs.open.alipay.com/194/106078/) [x]电脑网站支付(https://docs.open.alipay.com/270/105899/) ……

阅读全文

Caffeine Cache接入

Caffeine Cache接入 Caffeine Cache,目前最快的Java内存框架,堆内存。 接入方式: 1.引入pom文件 <dependency> <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> <version>2.7.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> 2.编写CaffeineConfig并注入CacheManager import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.caffeine.*; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.github.benmanes.caffeine.cache.Caffeine; import java.util.concurrent.TimeUnit; @Configuration @EnableCaching public class CaffeineConfig extends CachingConfigurerSupport { @Bean public CacheManager caffeineCacheManager() { CaffeineCacheManager cacheManager = new CaffeineCacheManager(); //定制化缓存Cache cacheManager.setCaffeine(Caffeine.newBuilder() .expireAfterWrite(3, TimeUnit.MINUTES) .initialCapacity(100) .maximumSize(10000)) ; return cacheManager; } } 3.通过注解使用 @Cacheable(cacheNames = "cache name", key = "#patam1+'-'+#param2") public void test(String param1,String param2){ } ……

阅读全文

Redis缓存

1.Redis简单介绍 语言开发的内存数据库,除了做KV缓存外还能做分布式锁、延时队列、定时任务等等 2.缓存读写模式/更新策略/处理流程 Cache Aside Pattern(旁路缓存模式) Read/Write Through Pattern(读写穿透) Write Behind Pattern(异步缓存写入) 3.为什么要用 Redis/为什么要用缓存? 简单来说使用缓存主要是为了提高接口响应速度,提升用户体验以及应对更多的用户。 高性能:对于高频数据并且不会经常改变的数据,保证下一次用户访问的数据直接从缓存中读取。 高并发:数据库的 QPS 大概都在 1w 左右(4 核 8g) ,但是使用 Redis 缓存之后很容易达到 10w+, > QPS(Query Per Second):服务器每秒可以执行的查询次数; 4.Redis 常见数据结构以及使用场景分析 4.1 String 普通操作: 127.0.0.1:6379> set key value #设置 key-value 类型的值 OK 127.0.0.1:6379> get key # 根据 key 获得对应的 value "value" 127.0.0.1:6379> exists key # 判断某个 key 是否存在 (integer) 1 127.……

阅读全文

JAVA IO流

Java IO流 Java 中 IO 流分为几种? 按照流的流向分,可以分为输入流和输出流; 输出流:从内存读出到文件。只能进行写操作。 输入流:从文件读入到内存。只能进行读操作。 输入和输出,都是相对于系统内存而言 按照操作单元划分,可以划分为字节流和字符流; 字节流:以字节为单位,每次次读入或读出是8位数据。可以读任何类型数据。(1byte(B) = 8bit(位)) 字符流:以字符为单位,每次次读入或读出是16位数据。其只能读取字符类型数据。(1字符=2字节 ) 按照流的角色划分为节点流和处理流。 节点流:直接与数据源相连,读入或读出。 处理流(Filter Stream):与节点流一块使用,在节点流的基础上,再套接一层,套接在节点流上的就是处理流。(DataInputStream、BufferedInputStream、BufferedReader等) Java Io流的40多个类都是从如下4个抽象类基类中派生出来的。 - InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。 - OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。 不同平台的换行符号: |符号|linux|windows|Java建议写法| |-|-|-|-| |换行符|\n|\r\n|System.getProperty(“line.separator”)| |路径分隔符|/|\|File.separator| |多个路径分隔符|:|;|File.pathSeparator| 字节流和字符流的区别: 字符流使用了缓存区(内存),执行了write(),文件中不会立刻有内容(除非缓冲区满了或者主动刷新缓冲区),需要等输出流对象关闭了,文件中才会有内容;字节流不使用缓冲区,执行了wirite(),文件中立刻就有内容了。 - ### 1.字符流 //步骤为:程序->字符流->缓存(数据先存放到缓存,再从缓存写入文件【主动刷新or流关闭】)->文件 import java.util.*; import java.io.*; public class WriterTest { public static void main(String[] args) { File file = new File("1.txt"); Scanner in = null; Writer out = null; try{ in = new Scanner(System.……

阅读全文

JAVA基础

Java基础知识 1. String 、StringBuilder 、StringBuffer String 类中使用 final 关键字修饰字符数组来保存字符串,private final char value[],所以 String 对象是不可变的。 每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象。StringBuffer 每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用 StringBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。 对于三者使用的总结: 操作少量的数据: 适用String 单线程操作字符串缓冲区下操作大量数据: 适用StringBuilder 多线程操作字符串缓冲区下操作大量数据: 适用StringBuffer 2.== 和 equals == : 它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象(基本数据类型==比较的是值,引用数据类型==比较的是内存地址)。 equals() : 它的作用也是判断两个对象是否相等。但它一般有两种使用情况: 情况1:类没有覆盖 equals() 方法。则通过 equals() 比较该类的两个对象时,等价于通过“==”比较这两个对象。 情况2:类覆盖了 equals() 方法。一般,我们都覆盖 equals() 方法来比较两个对象的内容是否相等;若它们的内容相等,则返回 true (即,认为这两个对象相等)。 说明: - String 中的 equals 方法是被重写过的,因为 object 的 equals 方法是比较的对象的内存地址,而 String 的 equals 方法比较的是对象的值。 - 当创建 String 类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有就把它赋给当前引用。如果没有就在常量池中重新创建一个 String 对象。……

阅读全文

Atomic

Atomic 是指一个操作是不可中断的。即使是在多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程干扰。 所以,所谓原子类说简单点就是具有原子/原子操作特征的类 public final int get() //获取当前的值 public final int getAndSet(int newValue)//获取当前的值,并设置新的值 public final int getAndIncrement()//获取当前的值,并自增 public final int getAndDecrement() //获取当前的值,并自减 public final int getAndAdd(int delta) //获取当前的值,并加上预期的值 boolean compareAndSet(int expect, int update) //如果输入的数值等于预期值,则以原子方式将该值设置为输入值(update) public final void lazySet(int newValue)//最终设置为newValue,使用 lazySet 设置之后可能导致其他线程在之后的一小段时间内还是可以读到旧的值。 基本数据类型原子类优势 - ①多线程环境不使用原子类保证线程安全(基本数据类型) class Test { private volatile int count = 0; //若要线程安全执行执行count++,需要加锁 public synchronized void increment() { count++; } public int getCount() { return count; } } ②多线程环境使用原子类保证线程安全……

阅读全文

ThreadLocal

ThreadLocal ThreadLocal是什么? ThreadLocal是一个本地线程变量副本工具类。 保存线程上下文信息,在任意需要的地方可以获取!!! ThreadLocal解决什么问题? 并发问题:使用 ThreadLocal 代替 Synchronized 来保证线程安全,同步机制采用空间换时间 -> 仅仅先提供一份变量,各个线程轮流访问,后者每个线程都持有一份变量,访问时互不影响。 数据存储问题: ThreadLocal 为变量在每个线程中创建了一个副本,所以每个线程可以访问自己内部的副本变量。 threadlocal在Spring中的使用->解决线程安全问题。 正常情况下,在Web中从接收请求到响应请求都应该属于同一个线程,而 ThreadLocal 是一个很好的机制,它为每个线程提供了一个独立的变量副本解决了变量并发访问的冲突问题,比如每个请求的用户信息。 ThreadLocal实践? 写一个验证token的切面 @Aspect @Component public class DemoAspect { @Pointcut("execution(* *.*..*Controller.*(..))") public void pointService(){ } @Around("pointService()") public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable { threadLocal.set(Object); //before Object obj = null; try { obj = joinPoint.proceed(); } catch (Throwable throwable) { ... } finally{ threadLocal.remove(); } //after return obj; } } 在请求方法中可以在任意地点获取存放的本地线程副本变量 ThreadLocal注意事项 如果使用ThreadLocal的set方法之后,没有显示的调用remove方法,就有可能发生内存泄露,所以养成良好的编程习惯十分重要,使用完ThreadLocal之后,记得调用remove方法。……

阅读全文

Volatile

并发编程3个重要特性 并发编程的三个重要特性原子性、可见性、有序性 原子性 即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。 可见性 可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。 有序性 即程序执行的顺序按照代码的先后顺序执行。 >java int a = 10; int b = 5; > 在Java内存模型中,允许编译器和处理器对指令进行重排序,但是重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。 ps:要想并发程序正确地执行,必须要保证原子性、可见性以及有序性。只要有一个没有被保证,就有可能会导致程序运行不正确。 volatile volatile语义 - 1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。(保证变量的可见性) - 2)禁止进行指令重排序。(保证有序性) 为什么不保证原子性:volatile修饰的属性若再修改前被另一个线程读取了值,那么修改后,无法改变已经复制到工作内存中的值。 volatile static int a=0; a++; // 包含了2步操作:1、读取a。2、执行a+1 & 将a+1结果赋值给a // 设:线程A、B同时执行以下语句,线程A执行完第1步后被挂起、线程B执行了a++,那么主存中a的值为1 // 但线程A的工作内存中还是0,由于线程A之前已读取了a的值 = 0,执行a++后再次将a的值刷新到主存 = 1 // 即 a++执行了2次,但2次都是从0变为1,故a的值最终为1 通过上图可知: Java内存模型规定所有的变量都是存在主存当中,每个线程都有自己的工作内存。线程对变量的所有操作都必须在自己的工作内存中进行,而不能直接对主存进行操作。并且每个线程不能访问其他线程的工作内存。 Java内存模型只保证了基本读取和赋值是原子性操作。 为什么保证可见性: - volatile修饰的属性能够保证每次读取都是最新的值 - 但在多线程下不会也无法更新已经读取了的值 (1)对于普通的成员变量不能保证可见性,因为普通共享变量被修改之后,什么时候被写入主存是不确定的,当其他线程去读取时,此时内存中可能还是原来的旧值,因此无法保证可见性。 (2)当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值。 为什么保证有序性重排序时,以volatile修饰的属性的读/写操作代码为分界线(lock前缀指令),读/写操作前的代码不允许排到后面,后面不允许排到前面,由此保证有序性。 使用条件: 您只能在有限的一些情形下使用 volatile 变量替代锁。要使 volatile 变量提供理想的线程安全,必须同时满足下面两个条件: - 对变量的写操作不依赖于当前值。 - 该变量没有包含在具有其他变量的不变式中。……

阅读全文