自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

li_w_ch的博客

没风的日子,我喜欢奔跑。

  • 博客(166)
  • 收藏
  • 关注

原创 数据库知识点小结

1、数据库的存储过程:存储过程是在大型数据库系统中,一组为了完成特定功能的SQL语句集,它存储在数据库中,一次编译后永久有效,通过用户指定存储过程的名字和参数来执行它。存储过程和函数的区别:一般来说,存储过程实现的功能要复杂一点,而函数的实现的功能针对性比较强 对于存储过程来说可以返回参数,而函数只能返回值或者表对象 存储过程一般是作为一个独立的部分来执行,而函数可以作为查询语句的一个部分来调用存储过程的优点:执行速度更快-在数据库中保存的存储过程语句都是编译过的 允许模块化程序设计

2021-04-15 21:10:56 470

原创 JVM面试题小结

1、java内存管理中的出现的典型问题:悬挂指针问题:一个指针引用了一个已经被回收的内存地址,导致程序的运行完全不可知。 内存泄漏:内存已经分配,但是已经没有了指向该内存的指针,导致内存泄漏。2、JVM加载class文件的原理机制:JVM中类的装载时由类加载器和它的子类来实现的,Java中的类加载器时一个重要的Java运行时系统组件,它负责在运行时查找和装入文件中的类。当java程序需要使用某个类时,JVM会确保这个类已经被加载,连接(验证、准备和解析)和初始化。类的加载是指把类的.cl

2021-04-14 16:36:42 503

原创 java使用IO和NIO两种方式实现文件拷贝

import java.io.*;import java.nio.ByteBuffer;import java.nio.channels.FileChannel;public class MyUtil { private MyUtil() { throw new AssertionError(); } public static void fileCopy(String source, String target) throws IOException .

2021-04-09 20:23:12 570

原创 java统计字符串在文件中出现的次数

问题描述:输入一个文件名和一个字符串,统计这个字符串在这个文件中出现的次数。import java.io.BufferedReader;import java.io.FileReader;/** * 输入一个文件名和一个字符串,统计这个字符串在这个文件中的出现次数 */public class Account { /** * 工具类中的方法都是静态方式访问的因此将构造器私有不允许创建对象 */ private Account() { t

2021-04-09 20:20:46 1504

原创 java使用IO流完成文件夹复制

问题描述:从源目录拷贝文件到目标目录。话不多说,代码实现:import java.io.*;/** * CopyDocJob定义了实际执行的任务,即从源目录拷贝文件到目标目录 */public class CopyDir2 { public static void main(String[] args) { try { copyDir("D:\\file1","D:\\file2"); } catch (IOExcepti

2021-04-09 19:57:57 394

原创 java多线程:向银行账户存钱

问题描述:100个线程同时向一个银行账户存入1元钱。1:使用同步机制银行账户类:/** * 银行账户类 * 演示100个线程同时向一个银行账户存入1元钱 * 未使用同步机制 */public class Account { // 账户余额 private double balance; /** * 存款 * @param money : 存入金额 */ public synchronized void deposit(d

2021-04-08 22:31:20 1026

原创 java创建n个线程,并保证线程同时启动

问题描述:给你n个赛车,让他们都在起跑线上就绪后,同时出发。解决方案:用一个for循环创建线程对象,同时调用wait()方法,让所有线程等待;直到最后一个线程页准备就绪后,调用notifyAll(),同时启动所有线程。思路:思路是,来一辆赛车就加上一把锁,并修改对应的操作数,如果没有全 部就绪就等待,并释放锁,直到最后一辆赛车到场后唤醒所有的赛车线程。代码:/** * n辆赛车,让他们都在起跑线上就绪后,同时出发 */public class CarCompetion { /

2021-04-08 20:37:43 3565 1

原创 java list与数组的相互转换

1:如果要把一个ArrayList直接转化为Object数组,则可以直接使用Object[] o = list.toArray();就可以了。2:转化为String数组,有以下两种方式:// 方法一String[] arr = new String[list.size];// 方法二String[] arr = (String[]) list.toArray(new String[0]);3:数组转换为List:String[] s = {"a", "b", "c"};List

2021-03-12 10:29:40 2366

原创 mybatis.type-aliases-package的作用和用法

在mapper.xml文件中的resultMap的type或者parameterType会用到自定义的POJO。例如:<mapper namespace="com.example.demo.mapper.UserMapper"> <select id="findAll" resultType="User"> select * from User </select> <select id="findByName" resu

2021-02-26 14:51:50 23456

原创 java8新增StampedLock详解

1、StampedLock概述StampedLock是并发包里面JDK8版本新增的一个锁,该锁提供了三种模式的读写控制,当调用获取锁的系列函数时,会返回一个long型的变量,我们称之为戳记(stamp),这个戳记代表了锁的状态。其中try系列获取锁的函数,当获取锁失败后会返回为0的stamp值。当调用释放锁和转换锁的方法时需要传入获取锁时返回的stamp值。StampedLock提供的三种读写模式的锁分别如下:写锁writeLock:是一个排它锁或者独占锁,某时只有一个线程可以获取该锁,当一个线

2021-01-18 21:17:05 2796 2

原创 信号量Semaphore详解

Semaphore信号量是java中的一个同步器,与CountDownLatch和CyclicBarrier不同的是,它内部的计数器是递增的,并且在一开始初始化Semaphore时可以指定一个初始值,但是并不需要知道需要同步的线程个数,而是在需要同步的地方调用acquire方法时指定需要同步的线程个数。1、案例1在主线程中开启两个子线程让它们执行,等所有子线程执行完毕后主线程再继续向下运行。import java.util.concurrent.ExecutorService;import

2021-01-18 20:17:22 4018 2

原创 回环屏障CyclicBarrier详解

CountDownLatch的计数器是一次性的,也就是等到计数器值变为0后,再调用CountDownLatch的await和countdown方法都会立刻返回,这就起不到线程同步的效果了。CyclicBarrier可以让一组线程全部达到一个状态后再全部同时执行。这里之所以叫做回环是因为所有等待线程执完毕,并重置CyclicBarrier的状态后它可以被重用。之所以叫做屏障是因为线程调用await方法后就会被阻塞,这个阻塞点就成为屏障点,等所有线程都调用了await方法后,线程就会冲破屏障,继续向下运行。

2021-01-18 17:35:13 351

原创 CountDownLatch详解

1、案例介绍在日常开发中经常会遇到需要在线程中开启多个线程去并行执行任务,并且主线程需要等待所有子线程执行完毕后再进行汇总的场景。在CountDownLatch出现之前一般都使用线程的join()方法来实现这一点,但是join()方法不够灵活,不能够满足不同场景的需要。使用CountDownLatch的代码如下:public class JoinCountDownLatch { // 创建一个CountDownLatch实例 private static volatile Co

2021-01-18 11:33:25 472 1

原创 ScheduledThreadPoolExecutor原理详解

ScheduledThreadPoolExecutor是一个可以在指定一定延迟时间后或者定时进行任务调度执行的线程池。ScheduledThreadPoolExecutor继承了ThreadPoolExecutor并实现了ScheduledExecutorService接口。线程池队列是DelayedWorkQueue,其和DelayedQueue类似,是一个延迟队列。三个重要方法:schedule(Runnable command, long delay, TimeUnit unit)方法

2021-01-16 20:48:35 1007

原创 Java线程池详解(面试)

1、线程池简介线程池主要解决两个问题:一是当执行大量异步任务时线程池能够提供较好的性能。在不使用线程池时,每当需要执行异步任务时直接new一个线程来运行,而线程的创建和销毁是需要开销的。线程池里面的线程是可复用的,不需要每次执行异步任务时都重新创建和销毁线程。二是线程池提供了一种资源限制和管理手段,比如可以限制线程的个数,动态新增线程等。2、java中提供的线程池Executors类提供了四种不同的线程池:newCachedThreadPool,newFixedThreadPool,newSch

2021-01-16 17:54:01 171

原创 ReentrantReadWriteLock原理详解

解决线程安全问题使用ReentrantLock就可以,但是ReentrantLock是独占锁,某时只有一个线程可以获取该锁,而实际中会有写少读多的场景,显然ReentrantLock满足不了这个需求,所以ReentrantReadWriteLock应运而生。ReentrantReadWriteLock采用读写分离的策略,允许多个线程可以同时获取读锁。读写锁内部维护了两个锁,一个用于读操作,一个用于写操作。所有ReadWriteLock实现都必须保证writeLock操作的内存同步效果也要保持与相关r

2021-01-16 15:08:37 3392

原创 ReentrantLock原理详解

ReentrantLock简介:ReentrantLock是可重入的独占锁,同时只能有一个线程可以获取该锁,其他获取该锁的线程会被阻塞而被放入该锁的AQS阻塞队列里面。ReentrantLock主要利用CAS+AQS队列来实现。它支持公平锁和非公平锁,两者的实现类似。从类图可以看到,ReentrantLock最终还是使用AQS来实现的,并且根据参数来决定其内部是一个公平还是非公平锁,默认是非公平锁。获取锁:1、void lock()方法当一个线程调用该方法时,说明该线程希望获取该

2021-01-15 20:56:15 3825

原创 AQS面试详解

1、AQS原理AQS(AbstractQueuedSynchronizer)抽象同步队列。是除了java自带的synchronized关键字之外的锁机制。它是实现同步器的基础组件,并发包中锁的底层就是使用AQS实现的。AQS类图如下:

2021-01-15 19:30:27 919

原创 java LockSupport类详解

1、LockSupport类简介LockSupport类,是JUC包中的一个工具类,是用来创建锁和其他同步类的基本线程阻塞原语。LockSupport类的核心方法有两个:park()和unpark(),其中park()方法用来阻塞当前调用线程,unpark()方法用于唤醒指定线程。这其实和Object类的wait()和singal()方法有些类似,但是LockSupport的这两种方法从语义上将比Object类的方法更清晰,而且可以针对指定线程进行阻塞和唤醒。LockSupport类使用了一种名

2021-01-15 17:11:02 1725

原创 java CopyOnWriteArrayList详解

Java并发包中的并发list只有CopyOnWriteArrayList。CopyOnWriteArrayList是一个线程安全的ArrayList,对其进行的修改操作都是在底层的一个复制数组(快照)上进行的,也就是使用了写时复制策略。写时复制(CopyOnWrite,简称COW)思想是计算机程序涉及领域中的一种优化策略。其核心思想是,如果多个调用者(Callers)同时要求相同的资源(如内存或者磁盘上的数据存储),他们会共同获取相同的指针指向相同的资源,直到某个调用者视图修改资源内容时,系统才会真正

2021-01-15 15:59:18 4167

原创 Java原子类:AtomicLong、LongAdder、LongAccumulator详解

JUC包提供了一系列的原子性操作类,这些类都是使用非阻塞算法CAS实现的,相比使用锁实现原子性操作,这在性能上有很大的提高。1、AtomicLongJUC并发包中包含有AtomicInteger、AtomicLong和AtomicBoolean等原子性操作类,它们的原理类似。AtomicLong是原子性递增或者递减类,其内部使用Unsafe来实现。多线程使用AtomicLong统计0的个数:// 统计0的个数public class Atomic { // 创建Long型原子计数

2021-01-12 20:06:46 1388

原创 Java中ThreadLocalRandom类原理剖析

1、概述ThreadLocalRandom类是JDK7在JUC包下新增的随机数生成器,它弥补了Random类在多线程下的缺陷。2、Random类及其局限性// java.util.Random的使用方法public class RandomTest { public static void main(String[] args) { // 创建一个默认种子的随机数生成器 Random random = new Random(); //

2021-01-12 16:48:37 503

原创 java中的锁详解

1、概述锁像synchronized同步块一样,是一种线程同步机制,但比java中的synchronized同步块更复杂。在java5之前锁是由synchronized同步块实现的,所以不能完全摆脱synchronized关键字。自Java5开始,java.util.concurrent.locks包中包含了一些锁的实现,因此你不用去实现自己的锁了。但是仍然需要了解一些锁的机制。2、乐观锁与悲观锁悲观锁是指对数据被外界修改持保守态度,任务数据很容易就会被其他线程修改,所以在数据被处理前先对数

2021-01-12 15:40:54 228

原创 Java伪共享详解

1、什么是伪共享在Cache内部是按行存储的,其中每一行称为一个Cache行。Cache行是Cache与主内存进行数据交换的单位,Cache行的大小一般为2的幂次数字节。当CPU访问某个变量时,首先会去看CPU Cache内是否有该变量,如果有则直接从中获取,否则就直接去主内存里面获取该变量,然后把该变量所在 内存区域的一个Cache行大小的内存复制到Cache中。由于存放到Cache行的是内存块而不是单个变量,所以可能会把多个变量存放到一个Cache行中。当多个线程同时修改一个缓存行里面的多个

2021-01-11 22:10:58 304 3

原创 java:CAS、ABA问题详解

1、java中的原子性操作所谓原子性操作,是指执行一系列操作时,这些操作要么全部执行,要么全部不执行,不存在只执行其中一部分的情况。2、CAS方法CAS即Compare and Swap,其是JDK提供的非阻塞原子性操作,它通过硬件保证了比较-更新操作的原子性。CAS有四个操作数,分别为:对象内存地址、对象中的变量的偏移量、变量预期值和新的值。其操作含义为:如果对象obj中内存偏移量为valueOffset的变量为expect,则使用新的值update替换旧的值expect。也就是说,更新一个变

2021-01-11 21:36:39 331

原创 java共享变量的内存可见性问题详解

1、并发和并行并发是指同一时间段内多个任务同时都在执行,并且都没有执行结束,而并行是在说单位时间内多个任务同时在执行。并发任务强调在一个时间段内同时执行,而一个时间段由多个单位时间累计而成,所以说并发的多个任务在单位时间内不一定同时在执行。在单CPU时代多任务都是并发执行的,这是因为单个CPU同时只能执行一个任务。在单CPU时代,多任务是共享一个CPU的,当一个任务占用CPU运行时,其他任务就会被挂起,当占用CPU的任务时间片用完后,会把CPU让给其他任务来使用。2、共享资源所谓共享资源,就

2021-01-11 20:24:22 1199 1

原创 java ThreadLocal用法详解

1、ThreadLocal简介在涉及到多线程需要共享变量的时候,容易出现并发问题,特别是在多个线程需要对一个共享变量进行写入时。为了保证线程安全,一般使用者在访问共享变量时需要进行适当的同步。同步的措施一般是加锁,是得在每个时刻只能有一个线程访问该变量,好处就是便于编码,缺点在于增加了线程间的竞争,降低了效率;第二个是使用ThreadLocal。如果说synchronized是以“时间换空间”,那么ThreadLocal就是以“空间换时间”,因为ThreadLocal的原理就是:对于要在线程间共享的变量

2021-01-10 18:49:14 2290 2

原创 java线程中断和死锁详解

1、线程中断:java中的线程中断是一种线程间的协作模式,通过设置线程的中断标志并不能直接终止该线程的执行,而是被终端的线程根据中断状态自行处理。void interrupt()方法:中断线程,例如,当线程A运行时,线程B可以调用线程A的interrupt()方法来设置线程A的中断标志为true并立即返回。设置标志仅仅是设置标志,线程A实际并没有被中断,它会继续执行下去。如果线程A因为调用了wait系列函数、join方法或者sleep方法而被阻塞挂起,这时候若线程B调用线程A的interrupt()

2021-01-10 16:15:26 448

原创 java线程详解

1、线程的概念线程是进程中的一个实体,线程本身是不会独立存在的。进程是代码在数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,线程则是进程的一个执行路径,一个进程中至少有一个线程,进程中的多个线程共享进程的资源。一个进程一直运行,直到所有的非守护线程都结束运行后才能结束。操作系统再分配资源时是把资源分配给进程的,但是CPU资源比较特殊,它是被分配到线程的,因为真正要占用CPU运行的是线程,所以说线程是CPU分配的基本单位。在Java中,当我们启动main函数时其实就启动了一个JVM的

2021-01-09 22:05:45 709

原创 二叉树中序遍历的三种方法

题目描述:给定一个二叉树的根节点root,返回它的中序遍历。方法一:递归思路与算法:二叉树的中序遍历:按照访问左子树-根节点-右子树的方式遍历这棵树,而在访问左子树或者右子树的时候我们按照同样的方式遍历,直到遍历这棵树,而在访问左子树或者右子树的时候我们按照同样的方式遍历,直到遍历完整棵树。因此整个遍历过程天然具有递归性质,我们可以直接用递归函数来模拟这一过程。定义inorder(root)表示当前遍历到root节点的答案,那么按照定义,我们只要递归调用inorder(root.left

2020-12-31 19:29:18 2239 3

原创 一文读懂java泛型

java泛型:Java泛型是JDK 5中引入的一个新特性,泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本质时参数化类型,也就是说所操作的数据类型被指定为一个参数。为什么要使用泛型程序设计:泛型程序设计意味着编写的代码可以被很多不同类型的对象所重用。假如我们有这样一个需求:编写一个排序方法,能够对整型数组、字符串数组甚至其他任何类型的数组进行排序,该如何实现?答案就是使用泛型。使用java泛型的概念,可以写一个泛型方法来对一个对象数组排序。然后,调

2020-12-28 22:24:03 127

原创 一文读懂java内部类

内部类概述:简单来说,内部类就是定义在另一个类中的类。而,需要内部类的主要原因有以下三点:内部类方法可以访问该类定义在所在的作用域中的数据,包括私有数据 内部类可以对同一个包中的其他类隐藏起来 当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较便捷内部类基础:广泛意义上的内部类一般包括四种:成员内部类 局部内部类 匿名内部类 静态内部类成员内部类:成员内部类时最普通的内部类,它的定义位于另一个类的内部,形如下面的形式:class Circle {

2020-12-28 21:13:59 141

原创 java高级特性lambda表达式详解

Lambda表达式,也可称为闭包,它是java 8中最重要的新特性。它允许把函数作为一个方法的参数(函数作为参数传递进方法中)。lambda表达式采用一种简洁的语法定义代码块,它是一个可传递的代码块,可以在以后执行一次或多次。lambda表达式的语法格式如下:(parameters) -> expression//或者(parameters) -> { statements; }lambda表达式特征:可选类型声明:不需要声明参数类型,编译器可以统一识别参数值 可选的

2020-12-26 21:54:18 316

原创 java对象克隆详解

先来看一下为一个包含对象引用的变量建立副本时会发生什么。原变量和副本都是同一个对象的引用,如图,这说明,任何一个变量改变都会影响另一个变量。Employee original = new Employee("John Public", 50000)Employee copy = original;copy.raiseSalary(10); // oops--also changed original如果希望copy是一个新对象,它的初始状态与original相同,但是之后它们各自会有.

2020-12-26 20:46:27 132

原创 java接口与抽象类详解

接口的概念:在java程序设计语言中,接口不是类,而是对类的一组需求描述,这些类要遵从接口描述的统一格式进行定义。编写接口的方式和类很相似,但是它们属于不同的概念,类描述对象的属性和方法。接口则包含类要实现的方法。除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在Java中,接口类型可用来声明一个变量,它们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。接口与类的区

2020-12-26 20:11:53 152

原创 java继承的设计技巧

1、将公共操作和域放在超类2、不要使用受保护的域有些人认为,将大多数的示例域定义为protected是一个不错的主意,只有这样,子类才能够在需要的时候直接访问它们。然而,protected机制并不能够带来更好的保护,其原因主要有两点:子类集合是无限制的,任何一个人都能够由某个类派生一个子类,并编写代码直接访问protected的实例域,从而破坏了封装性。 在java程序设计语言中,在同一个包中的所有类都可以访问proteced域,而不管它是否为这个类的子类。不过,protected方法对于指

2020-12-24 15:52:26 147

原创 java高级特性---反射机制详解

反射机制:javai反'z射机h制是在运机制行状态中,对于任意一个类,都能够知道这个类的所有属性和方法 ;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。简单来说,能够分析类能力的程序称为反射。反射的功能:在运行时判断任意一个对象所属的类 在运行时构造任意一个类的对象 在运行时判断任意一个类所具有的成员变量和方法 在运行时调用任意一个对象的方法 生成动态代理反射的用途:在日常的第三方应用开发过程中,经常会遇到

2020-12-24 13:06:57 162

原创 java继承详解

继承的概念:继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。何时使用继承:假设你在某个公司工作,这个公司中经理的待遇与普通员工的待遇存在着一些差异。不过,他么之间也存在着相同的地方,例如,他们都领薪水。只是普通雇员在完成本职任务之后仅领取薪水,而经理在完成了预期的业绩之后还能得到奖金。这种情形就需要使用继承。这是因为需要为经理定义一个新类Ma

2020-12-24 11:02:13 107

原创 java方法参数、重载与构造器

方法参数有两种调用类型,一是按按值调用,表示方法接收的是调用者提供的值。二是引用调用,表示方法接收的是调用者提供的变量地址。方法可以修改传递引用所对应的变量值,而不能修改传递值调用所对应的变量值。java程序设计语言 总是采用按值调用,也就是说,方法得到的是所有参数值的一个拷贝,特别是,方法不能修改传递给它的任何参数变量的内容。 public static void raiseSalary(int salary) { salary += 10000; Syst

2020-12-23 10:34:50 276 4

原创 使用LocalDate类显示当前月的日历

程序关键步骤:首先构造一个日历对象,并用当前的日期和时间进行初始化LocalDate date = LocalDate.now();// 获得当前的月和日int month = date.getMonthValue();int today = date.getDayOfMonth();将date设置为这个月的第一天,并得到这一天为星期几// set to start of monthdate = date.minusDays(today - 1);DayOfWeek weekd

2020-12-22 22:33:34 2623

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除