
java基础
文章平均质量分 74
java学习记录
maligebilaowang
七年数学建模经验,五一杯,电工杯,高教杯,美赛,华为杯都拿过多次一等奖,任何建模问题都可以找我!
展开
-
java基础:java泛型相关内容
集合容器类在设计阶段/声明阶段不能确定这个容器到底实际存的是什么类型的对象,所以在JDK1.5之前只能把元素类型设计为Object,JDK1.5之后使用泛型来解决。因为这个时候除了元素的类型不确定,其他的部分是确定的,例如关于这个元素如何保存,如何管理等是确定的,因此此时把元素的类型设计成一个参数,这个类型参数叫做泛型。这个类型参数将在使用时(例如,继承或实现这个接口,用这个类型声明变量、创建对象时确定(即传入实际的类型参数,也称为类型实参)。1、说一说泛型的用处主要是什么?原创 2023-04-03 23:09:46 · 230 阅读 · 0 评论 -
java基础:新特性Lambda表达式和stream数据流在开发中的应用
Exception in thread “main” java.lang.IllegalStateException: Duplicate key BikeParamBuilder.OrderInfo(id=1, orderNo=N001, goodsId=1, name=香蕉, price=2.3, num=2)list对象转化为map存在重复key,报错的情况。原创 2023-04-03 23:04:20 · 129 阅读 · 0 评论 -
java多线程:redis分布式锁在不同业务场景下的应用
首先,一个抽奖活动一个用户可以抽多次,-1问题出现的原因是因为这个用户疯狂的点击抽奖,前端没有限制,因此大量的请求发送到后台,当用户把抽奖次数耗光了,只剩下1次抽奖机会,两个请求同时过来,验证的时候发现剩余抽奖次数都是1,因此都可以进行抽奖,所以抽了两回,记录插入两回,剩余次数变成了1-2=-1。redis锁在这里的主要应用就是,针对缓存失效的情况,所有的评价配置获取请求都会走查询数据库,大量配置查询请求有可能打挂数据库,因此需要对评价配置请求进行并发控制;原创 2023-04-01 23:56:11 · 1364 阅读 · 1 评论 -
java基础:java基本数据类型详解
基本数据类型中,布尔类型boolean占有一个字节,由于其本身所代码的特殊含义,boolean类型与其他基本类型不能进行类型的转换(既不能进行自动类型的提升,也不能强制类型转换), 否则,将编译出错。java程序中可以直接操作基本数据类型,但是某些情况下需要将它们看成对象来处理,这些情况下就需要借助于Java API中基本数据类型对应的包装类来处理了。java是一门面向对象的语言,但是8中基本数据类型不具备面向对象的特征,所以实际使用中很不便所以为java八种基本数据类型提供了对应的包装类。原创 2023-03-23 14:56:29 · 2146 阅读 · 1 评论 -
java基础:Java中volatile关键字详解
大家都知道,计算机在执行程序时,每条指令都是在CPU中执行的,而执行指令过程中,势必涉及到数据的读取和写入。由于程序运行过程中的临时数据是存放在主存(物理内存)当中的,这时就存在一个问题,由于CPU执行速度很快,而从内存读取数据和向内存写入数据的过程跟CPU执行指令的速度比起来要慢的多,因此如果任何时候对数据的操作都要通过和内存的交互来进行,会大大降低指令执行的速度。因此在CPU里面就有了高速缓存。也就是,当程序在运行过程中,会将运算需要的数据从主存复制一份到CPU的高速缓存当中,那么CPU进行计算时就可原创 2023-03-22 23:03:12 · 1559 阅读 · 2 评论 -
Git常用命令大总结
Git常用命令大总结(持续总结)初始化本地仓库git init 指定目录作为初始化仓库git init 指定目录添加文件到暂存区git add 文件git add file1 file2 file3(添加多个文件)添加所有文件(包括更新的和添加的新文件)到暂存库git add . 提交到版本库,可以多次add,最后commit提交到版本库git commit -m"添加操作注释"本地仓库关联远程仓库$ git remote add ori原创 2021-07-27 23:46:02 · 133 阅读 · 1 评论 -
java基础:Java中this和super的用法总结
这几天看到类在继承时会用到this和super,这里就做了一点总结,与各位共同交流,有错误欢迎指正。原创 2023-03-21 23:39:14 · 560 阅读 · 2 评论 -
java基础:JAVA中重写equals()方法的同时要重写hashcode()方法
hashcode是用于散列数据的快速存取,如利用HashSet/HashMap/Hashtable类来存储数据时,都是根据存储对象的hashcode值来进行判断是否相同的。由于为了提高程序的效率才实现了hashcode方法,先进行hashcode的比较,如果不同,那没就不必在进行equals的比较了,这样就大大减少了equals比较的次数。原创 2023-03-21 23:10:38 · 1374 阅读 · 1 评论 -
java基础:深入理解java中的接口和抽象类
因为抽象类中含有无具体实现的方法,所以不能用抽象类创建对象。原创 2023-03-20 14:40:57 · 379 阅读 · 1 评论 -
java基础:hashCode() equals()总结
=1、hashCode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,hashCode是用来在散列存储结构中确定对象的存储地址的;2、如果两个对象相同,就是适用于equals(java.lang.Object) 方法,那么这两个对象的hashCode一定要相同;3、如果对象的equals方法被重写,那么对象的hashCode也尽量重写,并且产生hashCode使用的对象,一定要和equals方法中使用的一致,否则就会违反上面提到的第2点;原创 2023-03-20 11:25:08 · 302 阅读 · 2 评论 -
Java基础:hashCode() 和 equals()的问题详解
哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率。在Java的Object类中有一个方法:根据这个方法的声明可知,该方法返回一个int类型的数值,并且是本地方法,因此在Object类中并没有给出具体的实现。为何Object类需要这样一个方法?它有什么作用呢?不妨举个例子:假设内存中有0 1 2 3 4 5 6 7 8这8个位置,如果我有个字段叫做ID,那么我要把这个字段存放在以上8个位置之一,如果不用HashCode而任意存放,那么当查找时就需要到8个位置中去挨个原创 2023-03-17 18:20:00 · 877 阅读 · 1 评论 -
java基础:java中的static关键字解析
分析:当执行new Child()时,它首先去看父类里面有没有静态代码块,如果有,它先去执行父类里面静态代码块里面的内容,当父类的静态代码块里面的内容执行完毕之后,接着去执行子类(自己这个类)里面的静态代码块,当子类的静态代码块执行完毕之后,它接着又去看父类有没有非静态代码块,如果有就执行父类的非静态代码块,父类的非静态代码块执行完毕,接着执行父类的构造方法;另外,static块可以出现类中的任何地方(只要不是方法内部,记住,任何方法内部都不行),并且执行是按照static块的顺序执行的。原创 2023-03-15 22:34:22 · 692 阅读 · 1 评论 -
java基础:浅拷贝与深拷贝(实际开发中遇到的深拷贝问题)
将对象写入到io流中,反序列化是从io流中恢复对象;原创 2023-03-15 21:58:54 · 1465 阅读 · 1 评论 -
java基础:值传递与引用传递
如果参数类型是引用类型,那么传过来的就是这个引用参数的副本,这个副本存放的是参数的地址。如果在函数中改变了副本的地址,如new一个,那么副本就指向了一个新的地址,此时传入的参数还是指向原来的 地址,所以不会改变参数的值。但是不要被这个假象所蒙蔽,实际上这个传入函数的值是对象引用的拷贝,即传递的是引用的地址值,所以还是按值传递。如果参数类型是原始类型,那么传过来的就是这个参数的一个副本,也就是这个原始参数的值,这个跟之前所谈的传值是一样的。传递的是值的一份拷贝,这份拷贝与原来的值没什么关系。原创 2023-03-14 20:58:06 · 241 阅读 · 1 评论 -
java多线程(二六)ReentrantReadWriteLock读写锁详解(2)
通过上面的源码分析,我们可以发现一个现象:在线程持有读锁的情况下,该线程不能取得写锁(因为获取写锁的时候,如果发现当前的读锁被占用,就马上获取失败,不管读锁是不是被当前线程持有)。在线程持有写锁的情况下,该线程可以继续获取读锁(获取读锁时如果发现写锁被占用,只有写锁没有被当前线程占用的情况才会获取失败)。仔细想想,这个设计是合理的:因为当线程获取读锁的时候,可能有其他线程同时也在持有读锁,因此不能把获取读锁的线程“升级”为写锁;原创 2023-03-10 23:54:49 · 560 阅读 · 0 评论 -
java多线程(二五)ReentrantReadWriteLock读写锁详解(1)
现实中有这样一种场景:对共享资源有读和写的操作,且写操作没有读操作那么频繁。在没有写操作的时候,多个线程同时读一个资源没有任何问题,所以应该允许多个线程同时读取共享资源;但是如果一个线程想去写这些共享资源,就不应该允许其他线程对该资源进行读和写的操作了。针对这种场景,JAVA的并发包提供了读写锁ReentrantReadWriteLock,它表示两个锁,一个是读操作相关的锁,称为共享锁;一个是写相关的锁,称为排他锁,描述如下:线程进入读锁的前提条件:没有其他线程的写锁,原创 2023-03-10 23:44:35 · 364 阅读 · 0 评论 -
java多线程(二四)java多线程基础总结
在Java Web中要注意,线程是JVM级别的,在不停止的情况下,跟JVM共同消亡,就是说如果一个Web服务启动了多个Web应用,某个Web应用启动了某个线程,如果关闭这个Web应用,线程并不会关闭,因为JVM还在运行,所以别忘了设置Web应用关闭时停止线程。在很多情况下,主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运算,主线程往往将于子线程之前结束,但是如果主线程处理完其他的事务后,需要用到子线程的处理结果,也就是主线程需要等待子线程执行完成之后再结束,这个时候就要用到join()方法了。原创 2023-03-09 10:00:00 · 342 阅读 · 1 评论 -
java多线程(二三)并发编程:Callable、Future和FutureTask
我们前面说过通过这样的方式去创建线程的话,最大的好处就是能够返回结果,加入有这样的场景,我们现在需要计算一个数据,而这个数据的计算比较耗时,而我们后面的程序也要用到这个数据结果,那么这个时候Callable岂不是最好的选择?(1)未启动,FutureTask.run()方法还没有被执行之前,FutureTask处于未启动状态,当创建一个FutureTask,而且没有执行FutureTask.run()方法前,这个FutureTask也处于未启动状态。call()方法返回的类型就是传递进来的V类型。原创 2023-03-09 08:00:00 · 672 阅读 · 1 评论 -
java多线程(二十二)多线程编程之连续打印abc
主要的思想就是,为了控制执行的顺序,必须要先持有fontLock锁,也就是前一个线程要释放掉前一个线程自身的对象锁,当前线程再去申请自身对象锁,两者兼备时打印,之后首先调用thisLock.notify()释放自身对象锁,唤醒下一个等待线程,再调用fontLock.wait()释放prev对象锁,暂停当前线程,等待再次被唤醒后进入循环。运行上述代码,可以发现三个线程循环打印ABC,共10次。线程B等待A锁,再申请B锁,后打印B,再释放B锁,唤醒C,线程C等待B锁,再申请C锁,后打印C,再释放C锁,唤醒A。原创 2023-03-08 04:00:00 · 622 阅读 · 1 评论 -
java多线程(二一)并发协作生产者消费者设计模式
*** 资源/*资源序号*/ private int number = 0;/*资源标记*/ private boolean flag = false;/*** 生产资源//先判断标记是否已经生产了,如果已经生产,等待消费;//让生产线程等待 } catch(InterruptedException e) {原创 2023-03-07 20:01:05 · 581 阅读 · 2 评论 -
java多线程(二十)java多线程同步的五种方法(二)
它的原理是每次要线程要访问volatile修饰的变量时都是从内存中读取,而不是从缓存当中读取,因此每个线程访问到的变量值都是一样的。如果使用ThreadLocal管理变量,则每一个使用该变量的线程都获得该变量的副本,副本之间相互独立,这样每一个线程都可以随意修改自己的变量副本,而不会对其他线程产生影响。ReentrantLock类是可重入、互斥、实现了Lock接口的锁, 它与使用synchronized方法和块具有相同的基本行为和语义,并且扩展了其能力。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。原创 2023-03-07 00:08:20 · 242 阅读 · 1 评论 -
java多线程(十九)多线程同步的几种方法(一)
因为当我们有多个线程要同时访问一个变量或对象时,如果这些线程中既有读又有写操作时,就会导致变量值或对象的状态出现混乱,从而导致程序异常。举个例子,如果一个银行账户同时被两个线程操作,一个取100块,一个存钱100块。假设账户原本有0块,如果取钱线程和存钱线程同时发生,会出现什么结果呢?由于java的每个对象都有一个内置锁,当用此关键字修饰方法时,内置锁会保护整个方法。注: synchronized关键字也可以修饰静态方法,此时如果调用该静态方法,将会锁住整个类。截取了其中的一部分,是不是很乱,有些看不懂。原创 2023-03-06 23:37:18 · 146 阅读 · 1 评论 -
java多线程(十八)ThreadLocal的应用场景
1、ThreadLocal 的实现思想,我们在前面已经说了,每个线程维护一个 ThreadLocalMap 的映射表,映射表的 key 是 ThreadLocal 实例本身,value 是要存储的副本变量。ThreadLocal 实例本身并不存储值,它只是提供一个在当前线程中找到副本值的 key。如下图所示:2、线程隔离的秘密,就在于ThreadLocalMap这个类。原创 2023-03-06 00:03:49 · 727 阅读 · 2 评论 -
java多线程(十七)ThreadLocal实例分析
但是往往在多线程情况下我们不能保证每个线程的在调用 get 之前都调用了set ,所以最好对 initValue 进行覆写,以免导致空指针异常。因为在上面的代码分析过程中,我们发现如果没有先set的话,即在map中查找不到对应的存储,则会通过调用setInitialValue方法返回i,而在setInitialValue方法中,有一个语句是T value = initialValue(), 而默认情况下,initialValue方法返回的是null。3)在进行get之前,必须先set,否则会报空指针异常。原创 2023-03-05 23:56:51 · 310 阅读 · 1 评论 -
java多线程(十六)深入理解ThreadLocal类
如果map为空,则调用setInitialValue方法返回value。get()方法是用来获取ThreadLocal在当前线程中保存的变量副本,set()用来设置当前线程中变量的副本,remove()用来移除当前线程中变量的副本,initialValue()是一个protected方法,用来返回此线程局部变量的当前线程的初始值,一般是在使用时进行重写的,它是一个延迟加载方法,下面会详细说明。可能大家没有想到的是,在getMap中,是调用当期线程t,返回当前线程t中的一个成员变量threadLocals。原创 2023-03-05 23:53:43 · 468 阅读 · 1 评论 -
java多线程(十五)ThreadLocal介绍和理解
事实上,是不需要的。那么这种情况下使用ThreadLocal是再适合不过的了,因为ThreadLocal在每个线程中对该变量会创建一个副本,即每个线程内部都会有一个该变量,且在线程内部任何地方都可以使用,线程之间互不影响,这样一来就不存在线程安全问题,也不会严重影响程序执行性能。1、ThreadLocal提供了一种访问某个变量的特殊方式:访问到的变量属于当前线程,即保证每个线程的变量不一样,而同一个线程在任何地方拿到的变量都是一致的,这就是所谓的线程隔离。原创 2023-03-04 23:52:56 · 206 阅读 · 1 评论 -
java多线程(十三)死锁问题实例分析
可能会有多个线程形成了一个死锁的环路,比如:线程T1持有锁L1并且申请获得锁L2,而线程T2持有锁L2并且申请获得锁L3,而线程T3持有锁L3并且申请获得锁L1,这样导致了一个锁依赖的环路:T1依赖T2的锁L2,T2依赖T3的锁L3,而T3依赖T1的锁L1。从上面两个例子中,我们可以得出结论,产生死锁可能性的最根本原因是:线程在获得一个锁L1的情况下再去申请另外一个锁L2,也就是锁L1想要包含了锁L2,也就是说在获得了锁L1,并且没有释放锁L1的情况下,又去申请获得锁L2,这个是产生死锁的最根本原因。原创 2023-03-04 02:14:31 · 350 阅读 · 0 评论 -
Java并发编程:深入剖析ThreadLocal
这些变量不同于它们的普通对应物,因为访问某个变量(通过其 get 或 set 方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本。事实上,是不需要的。假如每个线程中都有一个connect变量,各个线程之间对connect变量的访问实际上是没有依赖关系的,即一个线程不需要关心其他线程是否对这个connect进行了修改的。1、ThreadLocal提供了一种访问某个变量的特殊方式:访问到的变量属于当前线程,即保证每个线程的变量不一样,而同一个线程在任何地方拿到的变量都是一致的,这就是所谓的线程隔离。原创 2023-03-04 00:01:17 · 326 阅读 · 0 评论 -
java并发--版本号字段解决并发更新数据引起的数据一致性问题
乐观锁机制采取了更加宽松的加锁机制。版本号控制实现乐观锁,解决并发过程中的数据不一致问题,提高系统吞吐量:一般是在数据表中加上一个数据版本号 version 字段,表示数据被修改的次数。当数据被修改时,version 值会+1。原创 2023-03-02 23:38:24 · 2064 阅读 · 0 评论 -
java原子性和原子操作理解
原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序不可以被打乱,也不可以被切割而只执行其中的一部分,将整个操作视作一个整体是原子性的核心特征。而此时又有一个线程去读取i的值,那么读取到的就是错误的数据。假若一个线程执行到这个语句时,我暂且假设为一个32位的变量赋值包括两个过程:为低16位赋值,为高16位赋值。原子性:即一个操作或者多个操作 要么全部执行 并且执行的过程不会被任何因素打断,要么就都不执行。举个例子:假如为一个32位的变量赋值过程不具备原子性的话,会发生什么后果?原创 2023-03-01 11:06:13 · 357 阅读 · 0 评论 -
java多线程(十一)join()方法
join() 定义在Thread.java中。join() 的作用:让“主线程”等待“子线程”结束之后才能继续运行。这句话可能有点晦涩,我们还是通过例子去理解// 主线程 public class Father extends Thread {s . join();. . . } } // 子线程 public class Son extends Thread {. . . } }说明:上面的有两个类Father(主线程类)和Son(子线程类)。原创 2023-02-28 17:02:14 · 4930 阅读 · 0 评论 -
java多线程(十)线程休眠
sleep() 定义在Thread.java中。sleep() 的作用是让当前线程休眠,即当前线程会从“运行状态”进入到“休眠(阻塞)状态”。sleep()会指定休眠时间,线程休眠的时间会大于/等于该休眠时间;在线程重新被唤醒时,它会由“阻塞状态”变成“就绪状态”,从而等待cpu的调度执行。原创 2023-02-28 15:21:09 · 894 阅读 · 0 评论 -
java多线程(九)线程让步
yield()的作用是让步。它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权;但是,并不能保证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权;也有可能是当前线程又进入到“运行状态”继续运行!原创 2023-02-27 21:01:28 · 250 阅读 · 0 评论 -
java多线程(八)线程等待与线程唤醒2
Object中的wait(), notify()等函数,和synchronized一样,会对“对象的同步锁”进行操作。wait()会使“当前线程”等待,因为线程进入等待状态,所以线程应该释放它锁持有的“同步锁”,否则其它线程获取不到该“同步锁”而无法运行!OK,线程调用wait()之后,会释放它锁持有的“同步锁”;而且,根据前面的介绍,我们知道:等待线程可以被notify()或notifyAll()唤醒。现在,请思考一个问题:notify()是依据什么唤醒等待线程的?原创 2023-02-27 20:55:47 · 378 阅读 · 0 评论 -
java多线程(七)线程等待与唤醒
在Object.java中,定义了wait(), notify()和notifyAll()等接口。wait()的作用是让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的锁。而notify()和notifyAll()的作用,则是唤醒当前对象上的等待线程;notify()是唤醒单个线程,而notifyAll()是唤醒所有的线程。Object类中关于等待/唤醒的API详细信息如下:notify() – 唤醒在此对象监视器上等待的单个线程。原创 2023-02-27 20:47:12 · 1037 阅读 · 0 评论 -
PG库分页查询数据丢失问题解决--线上bug
order by 的 sort 字段不使用索引(一般情况下,Sorted 字段也不使用索引),如果使用了索引,则会进行索引排序。原因主要是sql分页的时候没有加排序字段,然后pg就使用了默认排序字段group_id,而group_id字段是相同值,如果order by的列有相同的值时, 会随机选取这些行,具体根据执行计划有所不同。关系型数据库优化器在使用 order by limit 的时候,做了上面的优化,导致排序字段没有使用索引,使用堆排序。如果排序包含限制语句,则使用堆排序来优化排序过程。原创 2023-02-06 20:27:17 · 1453 阅读 · 1 评论 -
java多线程(六)synchronized关键字详解2
在java中,每一个对象有且仅有一个同步锁。这也意味着,同步锁是依赖于对象而存在。当我们调用某对象的synchronized方法时,就获取了该对象的同步锁。例如,synchronized(obj)就获取了“obj这个对象”的同步锁。不同线程对同步锁的访问是互斥的。也就是说,某时间点,对象的同步锁只能被一个线程获取到!通过同步锁,我们就能在多线程中,实现对“对象/方法”的互斥访问。 例如,现在有两个线程A和线程B,它们都会访问“对象obj的同步锁”。假设,在某一时刻,线程A获取到“obj的同步锁”并在执行原创 2022-12-07 20:59:20 · 170 阅读 · 0 评论 -
java多线程(五)synchronized关键字详解
1、为什么要引入同步机制在多线程环境中,可能会有两个甚至更多的线程试图同时访问一个有限的资源。必须对这种潜在资源冲突进行预防。解决方法:在线程使用一个资源时为其加锁即可。访问资源的第一个线程为其加上锁以后,其他线程便不能再使用那个资源,除非被解锁。2、程序实例用一个取钱的程序例子,来说明为什么需要引入同步。在使用同步机制前,整体程序如下:程序中定义了一个Bank类,其中包含了用户存储的钱(1000元),然后用两个线程进行取钱操作,可以看到尽管Bank类中的getMoney()方法对取钱数目与存款数据进原创 2022-12-05 20:20:23 · 209 阅读 · 0 评论 -
java多线程(四)线程池的实现原理剖析
线程池实现原理和源码解析原创 2022-12-01 19:48:03 · 156 阅读 · 0 评论 -
java多线程(三)线程池的使用以及案例
在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题:如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务?在Java中可以通过线程池来达到这样的效果。原创 2022-11-29 18:13:23 · 546 阅读 · 0 评论