![](https://img-blog.csdnimg.cn/20201014180756913.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
Java
文章平均质量分 69
那股哇
这个作者很懒,什么都没留下…
展开
-
StringTable
文章目录一、String的基本特性不可变性一道面试题二、String的内存分配三、String的基本操作四、字符串拼接操作五、intern()的使用两种创建对象方式JDK6与JDK7/8对比一、String的基本特性String声明为final,不可被继承实现了Serializable接口,支持序列化;实现了Comparable接口,字符串可以比较大小在Java8及以前使用char[]存储字符串,在Java9后改用byte[],数组创建后大小不可变不可变性字符串重现赋值时,需要重新指定原创 2021-03-18 16:26:42 · 165 阅读 · 1 评论 -
对象实例化、内存布局、访问定位
文章目录对象实例化对象的内存布局对象访问定位对象实例化加载类元信息 虚拟机遇到一条new指令,首先去检查这个指令的参数能否在Metaspace的常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已经被加载、解析和初始化。(即判断类元信息是否存在)。如果没有,那么在双亲委派模式下,使用当前类加载器以ClassLoader+包名+类名为Key进行查找对应的.class文件。如果没有找到文件,则抛出ClassNotFoundException异常,如果找到,则进行类加载,并生成对应的C原创 2021-03-15 16:08:54 · 141 阅读 · 0 评论 -
运行时数据区(方法区)
文章目录栈、堆、方法区的交互关系方法区概述HotSpot中方法区的演进设置方法区大小与OOM方法区的内部结构类型信息域(Field)信息方法信息non-final的类变量栈、堆、方法区的交互关系方法区概述方法区看作一块独立于Java堆的内存空间,是各个线程共享的内存区域方法区在Java虚拟机启动时被创建,其实际的物理内存空间和Java堆一样,可以是不连续的,方法区的大小可以是固定大小或者是可扩展空间,关闭JVM会释放这个区域的内存方法区的大小决定了系统可以保存多少个类,如果系统定义了太多类,原创 2021-03-12 21:01:56 · 214 阅读 · 0 评论 -
运行时数据区(堆)
概述一个JVM实例只存在一个堆内存Java堆在JVM启动时即被创建,其空间大小也确定了堆可以处在物理上不连续的空间中,但是在逻辑上应该被视为连续的在方法结束后,堆中的对象不会被马上移除,仅仅在垃圾收集的时候才会被移除-Xms用于表示堆区的起始内存,等价于-XX:InitialHeapSize-Xmx用于表示堆区的最大内存,等价于-XX:MaxHeapSize通常会将-Xms和-Xmx两个参数配置相同的值,其目的是为了避免频繁的扩容与垃圾回收,从而提高性能堆空间参数设置:https://do原创 2021-03-09 18:39:51 · 188 阅读 · 0 评论 -
运行时数据区(PC寄存器、虚拟机栈、本地方法栈)
运行时数据区在运行时数据区中,红色部分是由所有线程共享的数据区灰色部分是线程隔离的数据区程序计数器PC寄存器是一块较小的内存区域,可以看作当前线程所执行的字节码指令的行号指示器作用:PC寄存器用来存储指向下一条指令的地址,由执行引擎读取下一条指令每个线程都有自己的程序计数器,是线程私有的,生命周期与线程的生命周期保持一致任何时间一个线程都只有一个方法在执行,就是当前方法。程序计数器会存储当前线程正在执行的Java方法的JVM指令地址;如果是在执行native方法,则是未原创 2021-03-06 21:58:40 · 170 阅读 · 0 评论 -
虚拟机类加载机制
类加载的时机类的生命周期有七个阶段其中,加载、验证、准备、初始化和卸载这五个阶段顺序是确定的,而解析阶段在某些情况下可以在初始化阶段之后进行主动引用:在初始化阶段,《Java虚拟机规范》严格规定了六种情况必须立即对类进行初始化遇到new、getstatic、putstatic、invokestatic四条字节码指令,类若果未进行过初始化,需要先进行初始化。能够生成这四条指令的典型场景: 使用new关键字实例化对象 读取或设置一个类型的静态字段时(被final修饰、已在编译器把结原创 2021-03-01 23:00:37 · 95 阅读 · 0 评论 -
Callable和Future用法解析
Callable和Future的关系可以用Future.get来获取Callable接口返回的执行结果,还可以通过Future.isDone()来判断任务是否已经执行完了在call()未执行完毕之前,调用get()的线程(假定此时是主线程)会被阻塞,直到call方法返回了结果后,此时future.get才会得到结果,然后主线程才会切换到runnable状态Future是一个存储器,存储了call()这个任务的结果,而这个任务的执行时间是无法提前确定的Future主要方法get():获取结果。原创 2021-01-28 18:07:08 · 4259 阅读 · 0 评论 -
控制并发流程的方式
CountDownLatch即倒数栅栏,有两种典型用法:一等多、多等一await():调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行countDown():将count()值减1,直到为0时,等待的线程会被唤醒CountDownLatch(int count):构造函数,参数count为需要倒数的数值一等多:一个线程等待多个线程都执行完毕,再继续自己的工作模拟工厂中,质检流程,5个质检工人检查,所有人都认为通过,才算通过 public cla原创 2021-01-27 22:55:06 · 167 阅读 · 2 评论 -
final关键字与不变性
不变性如果对象在被创建后,状态不能被修改,那么它就是不可变具有不变性的对象一定是线程安全的对象不可变的判断条件对象创建后,其状态不能改变所有属性都是final修饰的对象创建过程中没有发生逸出final的三种用法final修饰变量含义:被final修饰的变量,意味着值不能被修改。如果变量是对象,那么对象的引用不能变,但是对象自身的内容依然可以改变public class Person { final int age = 18; final String name原创 2021-01-26 17:55:21 · 138 阅读 · 4 评论 -
什么是CAS?
什么是CAS?CAS即Compare And Swap,就是把一个期望值与变量的当前值进行比较,如果当前变量的值与期望值相等,就使用这个新值来代替当前变量的值。下面是模拟CAS的代码:public class SimulatedCAS { private volatile int value; public synchronized int compareAndSwap(int expectedValue, int newValue){ int oldVal原创 2021-01-26 15:34:00 · 639 阅读 · 0 评论 -
Java中的锁--分类辨析
Lock接口为什么有synchronized了还要用Lock?效率低:锁的释放情况少、试图获得锁时不能设定超时、不能中断一个正在试图获得锁的线程不够灵活(读写锁更灵活):加锁和释放的时机单一、每个锁仅有单一的条件(某个对象)无法知道是否成功获取到锁主要方法:lock()lock()就是最普通的获取锁。如果锁被其他线程获取,则进行等待Lock不会像synchronized一样在异常时自动释放锁最佳实践应该是在finally中释放锁,以保证发生异常时锁一定被释放lock(.原创 2021-01-26 01:21:19 · 88 阅读 · 0 评论 -
ThreadLocal用法、原理
一、ThreadLocal两大使用场景场景一每个线程需要一个独享的对象,即该对象在线程间隔离(通常是工具类,典型需要使用的类有SimpleDateFormat和Random)下面程序中用ThreadSafeFormatter初始化了SimpleDateFormat实例,在每个线程调用时,都是一个独立的对象,做到了线程间的隔离public class ThreadLocalNormalUsage05 { public static ExecutorService threadPool =原创 2021-01-20 16:08:21 · 212 阅读 · 2 评论 -
JMM内存模型--重排序、可见性、原子性
为什么需要JMM(Java Memory Model)?C语言不存在内存模型的概念,很多行为依赖于处理器,不同处理器的操作会导致运行结果不一样,所以不能保证并发安全JMM是一组规范,也是工具类和关键字的原理JMM最重要的三点内容:重排序、可见性、原子性一、重排序1、重排序例子下面是一个演示重排序的例子,一个线程执行a = 1; x = b,一个线程执行b = 1; x = bpublic class OutOfOrderExecution { private static .原创 2021-01-18 15:33:27 · 172 阅读 · 0 评论 -
多线程核心8-3:线程三大安全问题之发布与逸出
发布与逸出的概念发布:对象能够在作用域范围外被使用,则这个对象被发布出去了逸出:被发布到了不该发布的地方,以下是逸出的两种情况:方法返回一个private对象未完成初始化(构造函数还未执行完毕)就将对象提供给外界在构造函数中未完成初始化完毕就用this赋值隐式逸出–注册监听事件构造函数中运行线程例子与解决方法方法返回private对象的情况在例子中return了一个private修饰的对象,即将该私有对象发布出去了 public class MultiThreadEr原创 2021-01-14 00:01:19 · 223 阅读 · 2 评论 -
多线程核心8-2:线程三大安全问题之死锁
一个必然死锁的例子public class MultiThreadError2 implements Runnable { int flag = 0; static Object o1 = new Object(); static Object o2 = new Object(); public static void main(String[] args) { MultiThreadError2 r1 = new MultiThreadError2();原创 2021-01-13 21:42:28 · 84 阅读 · 0 评论 -
多线程核心8-1:线程三大安全问题之运行结果错误
两个线程导致的错误两个线程进行index++操作,两个线程会相互干扰,导致结果不一定准确,现在想找出出错的位置和出错次数public class MultiThreadError1 implements Runnable { static MultiThreadError1 instance = new MultiThreadError1(); int index = 0; public static void main(String[] args) throws Inte原创 2021-01-13 21:38:48 · 135 阅读 · 0 评论 -
多线程核心7:处理未捕获的异常
使用UncaughtExceptionHandler的原因主线程可以轻松发现异常,子线程不能子线程的异常无法用传统方式捕获在捕获到异常时也能进行处理,提高健壮性全局异常处理使用方式实现Thread.UncaughtExceptionHandler接口public class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler { private String name; public原创 2021-01-06 20:33:41 · 111 阅读 · 0 评论 -
多线程核心6:线程的属性
线程Id线程的Id不是从0开始,而是从1开始,原因是先做了++操作线程id会自动递增,在创建线程时,不单是创建了一个主线程和一个子线程,jvm 也创建了一系列线程,因此子线程 Id 并不是2public class ID { public static void main(String[] args) { Thread thread = new Thread(); System.out.println(Thread.currentThread().getId.原创 2021-01-06 19:43:58 · 116 阅读 · 0 评论 -
多线程核心5:Thread和Object类中线程相关方法
一、wait()、notify()、notifyAll()wait():导致当前线程等待,直到另一个线程调用此对象的notify()方法或notifyAll()方法,或指定的时间已过。 即释放所拥有的monitor,直到重新获得注意:wait()要在同步代码块中使用,是为了防止拥有notify()的线程先执行了,导致死锁notify()和notifyAll():分别是唤醒单个线程和所有线程public class Wait { public static Object object原创 2021-01-06 18:58:38 · 108 阅读 · 0 评论 -
多线程核心4:线程的六种状态
状态转换图一般把Blocked(被阻塞)、Waiting(等待)、Timed_waiting(计时等待)都称为阻塞状态六种状态具体代码线程刚创建好,还未启动,这时属于NEW状态,线程处于就绪状态或者正在运行,都是属于RUNNABLE,运行结束,进入TERMINATEDpublic class NewRunnableTerminated implements Runnable { @Override public void run() { for (int i原创 2021-01-04 16:58:19 · 136 阅读 · 0 评论 -
多线程核心3:线程的正确停止方式
正确方式如何正确的停止线程?原理:使用interrupt来通知,而不是强制原因是通常情况下会认为发出停止请求的线程并不清楚被停止的线程的状态和细节,所以要把停止的决定权交给线程本身,而不是其它线程通常线程会在什么情况下停止?run方法中所有的代码运行完毕run方法中有异常出现,但未被捕获处理使用正确方法停止线程会有以下几种情况:run方法内没有sleep或wait方法,停止线程main线程和Thread-0线程要相互配合才能起到作用/** * 在子线程Thread-原创 2021-01-02 20:52:57 · 150 阅读 · 0 评论 -
多线程核心2:多线程启动方式
start()与run()启动public class StartAndRunMethod { public static void main(String[] args) { Runnable runnable = () -> { System.out.println(Thread.currentThread().getName()); }; runnable.run(); new Thread(r原创 2021-01-01 14:22:43 · 122 阅读 · 0 评论 -
多线程核心1:实现多线程的方式
实现多线程的方法实现Runnable接口public class RunnableStyle implements Runnable { public static void main(String[] args) { Thread thread = new Thread(new RunnableStyle()); thread.start(); } @Override public void run() { Sys原创 2021-01-01 01:44:00 · 146 阅读 · 4 评论 -
Synchronized基本用法、性质和原理
Synchronized的两种用法Synchronized作用:能够保证在同一时刻最多只有一个线程执行该代码,以达到保证并发安全的效果对象锁方法锁:Synchronized修饰普通方法,默认锁对象为this当前实例对象同步代码块锁:手动指定锁对象类锁Synchronized修饰静态的方法指定锁为Class对象,类锁只能在同一时刻被一个对象拥有多线程访问同步方法的7种情况两个线程同时访问一个对象的同步方法争抢同一把锁,相互等待public class Sy原创 2020-12-31 21:59:37 · 101 阅读 · 0 评论 -
JVM系列笔记--字节码与类加载
一、字节码指令反编译可使用javap -v className.class来反编译class文件public class Demo3_1 { public static void main(String[] args) { int a = 10; int b = Short.MAX_VALUE + 1; int c = a + b; System.out.println(c); }}Classfile /D:/dow原创 2020-11-10 16:24:03 · 174 阅读 · 0 评论 -
JVM系列笔记--垃圾回收
对象回收引用计数法在对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加一;当引用失效时,计数器值就减一;任何时刻计数器为零的对象就是不可能再被使用的public class ReferenceCoutingGC { public Object instance = null; private static final int _1MB = 1024*1024; private byte[] bigSize = new byte[2 * _1MB]; p原创 2020-11-05 17:07:05 · 156 阅读 · 0 评论 -
JVM系列笔记--内存结构
运行时的数据区域程序计数器程序计数器(Program Counter Register)是一块较小的内存空间,是当前线程所执行的字节码的行号指示器,作用是用来选取下一条需要执行的字节码指令各条线程之间计数器互不影响,独立存储,线程私有的内存区域如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是本地(Native)方法,这个计数器值则应为空此区域不会有内存溢出(OutOfMemoryError)虚拟机栈每一个方法被调用直至执行完毕的原创 2020-11-03 23:36:05 · 83 阅读 · 0 评论 -
Spring Boot系列笔记--整合Redis
基本环境搭建导入依赖<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId></dependency>配置文件配置Redis主机地址,端口默认6379spring.redis.host=127.0.0.1RedisTemplate.原创 2020-10-29 17:31:41 · 138 阅读 · 1 评论 -
Spring Boot系列笔记--缓存
Spring缓存抽象CacheManager管理多个Cache组件的,对缓存的真正CRUD操作在Cache组件中,每一个缓存组件有自己唯一一个名字使用缓存即要使用相同的数据时,直接从缓存中获取,而不用调用方法查询数据库缓存注解@Cacheable@Cacheable标注的方法执行之前先来检查缓存中有没有这个数据,默认按照参数的值作为key去查询缓存,如果没有就运行方法并将结果放入缓存;以后再来调用就可以直接使用缓存中的数据几个属性:cacheNames/value:指定缓存组件的名字原创 2020-10-28 22:12:42 · 183 阅读 · 1 评论 -
Spring Data Jpa总结--查询方式、多表关系
Spring Data Jpa基本说明操作步骤创建实体类,建立与数据表的关联编写一个符合Jpa规范的Dao层接口完成CRUD操作接口说明JpaRepository<实体类类型, 主键类型>:接口中封装了一些基本的增删查改方法JpaSpecificationExecutor<实体类类型>:完成一些复杂操作,如分页查询,可完成动态查询,即自定义查询条件@Testpublic void testSpec(){//查询 //自定义查询条件 S原创 2020-10-26 16:04:33 · 137 阅读 · 0 评论 -
Spring Boot系列笔记--数据访问
一、JDBCSpringBoot使用JDBC只需导入相应依赖<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency> <groupId>mysql</groupId>原创 2020-10-16 22:55:54 · 103 阅读 · 0 评论 -
Spring Boot系列笔记--扩展SpringMVC
一、扩展使用xml文件来配置springmvc,如:<mvc:view-controller path="/hello" view-name="success"/> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/hello"/> <bean></bean> </mvc:interceptor>原创 2020-10-14 16:04:12 · 92 阅读 · 0 评论 -
Spring Boot系列笔记--静态资源映射规则
一、webjarsWebJars是以Jar形式为Web项目提供资源文件,然后借助Maven这些依赖库的管理,保证这些Web资源版本唯一性。在spring boot源码中有一个自动配置类WebMvcAutoConfiguration.class,其中关于webjars的代码如下:...public void addResourceHandlers(ResourceHandlerRegistry registry) { if (!this.resourceProperties.i原创 2020-10-14 15:33:24 · 99 阅读 · 0 评论 -
Spring Boot系列笔记--配置文件
一、yaml语法基本语法K: V,:后必须跟一个空格;通过空格缩进来控制层级server: port: 8081 path: /hello字面量写法字符串默认不用加上单引号或者双引号; "":双引号;不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思name: "zhangsan \n lisi" 输出;zhangsan 换行 lisi'':单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据 name: 'zhangsan \n lisi'原创 2020-10-08 22:06:26 · 95 阅读 · 0 评论 -
Spring Boot系列笔记--HelloWorld
一、编写helloworld过程创建maven工程(jar)导入springboot相关依赖<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version></parent><depe原创 2020-10-08 19:30:57 · 62 阅读 · 0 评论 -
Spring注解驱动开发--自动装配
一、使用@Autowired默认优先按照类型去容器中找对应的组件,需要使用时自动注入(applicationContext.getBean(BookService.class);)package org.hao.service;import org.hao.dao.BookDao;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;原创 2020-09-24 23:16:34 · 84 阅读 · 0 评论 -
Spring注解驱动开发--属性赋值
一、@Value赋值配置文件方式:用property给Bean赋值<bean id="person" class="org.hao.bean.Person"> <property name="age" value="18"></property> <property name="name" value="张三"></property> </bean>注解方式:用@Value注解publi原创 2020-09-24 20:39:08 · 126 阅读 · 0 评论 -
Spring注解驱动开发--生命周期
一、@Bean指定初始化和销毁方法在@Bean注解里指定init-method和destory-method @Bean(initMethod = "init", destroyMethod = "destory")二、InitializingBean和DisposableBean让Bean实现InitializingBean(定义初始化逻辑)和DisposableBean(定义销毁逻辑)接口package org.hao.bean;import org.springframewo原创 2020-09-24 16:56:16 · 70 阅读 · 0 评论 -
Spring注解驱动开发--注册组件
一、@Configuration、@Bean给容器中注册组件配置文件方式<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springfram原创 2020-09-23 22:42:49 · 111 阅读 · 0 评论 -
MyBatis笔记(Java EE 互联网轻量级框架整合开发)
一、MyBatis核心组件SqlSessionFactoryBuilder(构造器):根据配置或代码来生成SqlSessionFactory,采用的是分步构建的Builder模式。SqlSessionFactory(工厂模式):生成SqlSession,使用工厂模式。SqlSession(会话):一个既可以发送SQL执行返回结果,也可以获取Mapper的接口。一般让其在业务逻辑代码中消失,使用MyBatis提供的SQL Mapper接口编程技术。SQL Mapper(映射器):由一个Java接口和原创 2020-09-11 13:27:18 · 126 阅读 · 0 评论