- 博客(101)
- 收藏
- 关注
原创 文件系统简介
文件系统是操作系统中负责管理持久数据的子系统,说简单点,就是负责把用户的文件存到磁盘硬件中,因为即使计算机断电了,磁盘里的数据并不会丢失,所以可以持久化的保存文件。文件系统的基本数据单位是文件,它的目的是对磁盘上的文件进行组织管理,那组织的方式不同,就会形成不同的文件系统。Linux最经典的一句话是:「一切皆文件」,不仅普通的文件和目录,就连块设备、管道、socket 等,也都是统一交给文件系统管理的。Linux。
2024-12-01 21:11:33 638
原创 TCP/IP协议
一句话,主要防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误。如果使用的是两次握手建立连接,假设有这样一种场景,客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中滞留的时间太长了,由于TCP的客户端迟迟没有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。
2024-12-01 20:37:19 652
原创 OSI七层参考模型
肯定要知道对方的IP地址,这是最基本的,就像你要访问百度,肯定得知道百度的域名,域名就是百度的IP地址。在讲网络层之前,其实基于广播的这种通信就可以实现全世界通信了,你吼一声,如果全世界是一个局域网,全世界的计算机肯定可以听得见,从理论上似乎行得通,如果全世界的计算机都在吼,你想一想,这是不是一个灾难。实际上这个七层是不存在的。数据链路层中会把网络层的数据包封装到数数据链路层的数据位置,然后再添加上自己的包头,再发给物理层,物理层发给网关,网关再发给对方教室的网关,对方教室的网关收到后在那个教室做广播。
2024-11-30 23:21:31 554
原创 零拷贝与内存映射
先简单介绍一下磁盘与内存之间数据传输的方式:硬盘(磁盘)和内存之间数据传送的两种方式:PIO模式和DMA模式PIO(Programming Input Output,编程输入输出)模式下通过CPU来控制硬盘和内存之间的数据传输,是一种通过CPU执行I/O端口指令来进行数据的读写的数据交换模式。显然这种方式是不合理的,因为它需要占用大量的CPU时间来读取文件,造成文件访问时系统几乎停止响应。DMA(Direct Memory Access,直接内存访问)取代了PIO,它可以不经过CPU而直接进行磁盘和内存(内
2024-11-30 22:10:29 606
原创 计算机基础
在对CPU、缓存、内存、硬盘等概念进行详细介绍之前,先通过一个流程图来直观了解一下这几个组件之间的关系。主存就是狭义上的内存,广义上的内存包括主存和缓存。按照与CPU的接近程度,存储器分为与,简称内存与外存。内存储器又常称为主存储器(简称主存),属于主机的组成部分;外存储器又常称为辅助存储器(简称),属于外部设备。CPU不能像访问内存那样,直接访问外存,外存要与CPU或I/O设备进行数据传输,必须通过内存进行。在80386以上的高档微机中,还配置了高速缓冲存储器(cache),这时内存包括主存与两部分。
2024-11-24 23:16:41 827
原创 mybatis连接数据库底层原理
这行代码中的child.evalNode("dataSource")方法,该方法的作用就是解析< dataSource >标签及其子标签的属性值,获取数据库连接属性,如下图所示。这三种连接数据库属性的配置方式,任选一种即可,也可以三种方式混合使用。Mybatis在加载这些属性时,首先读取第一种方式配置的,其次读取第二种方式配置的,最后读取第三种方式配置的,如果三种方式中存在同名属性,先读取的属性会被后读取的属性覆盖,即第三种配置方式的优先级高于第二种方式,第二种方式的优先级高于第一种方式。
2024-11-24 22:57:36 873
原创 SpringMVC原理详解
SpringMVC是一种基于Java实现的MVC设计模式的轻量级Web框架,它是Spring框架的一部分,主要用于简化Web开发。 SpringMVC采用MVC架构模式,将应用程序分为模型(Model)、视图(View)和控制器(Controller)三个层次,从而实现业务逻辑、数据和界面的分离。模型层负责处理数据,视图层负责展示数据,而控制器层则负责根据输入调用相应的模型和视图。SpringMVC的优点包括结构松散、易于扩展和与Spring框架无缝集成。
2024-11-17 23:27:48 970
原创 SpringMVC简单使用
MVC模型:是一种架构的新模式,本身不引入新的功能,只是帮助我们将开发的结构组织的更加合理。使展示与模型分离,流程逻辑控制、业务逻辑调用与展示逻辑分离。M(model模型):数据模型,包含要展示的数据和业务。V(View视图):用户界面,在界面上展示模型数据。C(Controller控制器):起调度作用,接收用户请求,调用业务处理请求,共享数据模型并跳转界面。使用方式有两种,现在基本上都是使用第二种方式:1、基于XML配置与注解的方式使用Spring MVC。
2024-11-17 22:45:04 953
原创 G1垃圾收集器
XX:G1HeapWastePercent(默认5%): gc过程中空出来的region是否充足阈值,在混合回收的时候,对Region回收都是基于复制算法进行的,都是把要回收的Region里的存活对象放入其他Region,然后这个Region中的垃圾对象全部清理掉,这样的话在回收过程就会不断空出来新的Region,一旦空闲出来的Region数量达到了堆内存的5%,此时就会立即停止混合回收,意味着本次混合回收就结束了。(Shenandoah优化成多线程收集了)
2024-11-17 21:53:59 932
原创 CMS垃圾收集器详解
因此对于老年代来说,引用了老年代中对象的新生代对象,也会被老年代视作“GC ROOTS”。CMS前五个阶段都是标记存活对象的,除了“初始标记”和“重新标记”阶段会stop the word ,其它三个阶段都是与用户线程一起运行的,就会出现这样的情况:gc线程正在标记存活对象,用户线程同时从年轻代向老年代提升新的对象,清理工作还没有开始,old gen已经没有空间容纳更多对象了,这时候就会导致concurrent mode failure, 然后就会使用串行收集器回收老年代的垃圾,导致停顿的时间非常长。
2024-11-17 21:35:05 671
原创 JVM的垃圾回收机制
即使在可达性分析算法中不可达的对象,也并非是“非死不可”,这时候它们暂时处于“缓刑”阶段,要真正宣告一个对象死亡,至少要经历两次标记过程。第一次标记:如果对象在进行可达性分析后发现没有与GC Roots相连接的引用链,那它将会被第一次标记;第二次标记:第一次标记后接着会进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法。在finalize()方法中没有重新与引用链建立关联关系的,将被进行第二次标记。
2024-11-17 21:27:57 991
原创 对象的创建过程
一个Java对象的创建过程就是类实例化的过程,往往会包括类初始化的过程,在第一次创建一个类的对象时,就需要对类进行初始化,以后再创建这个类的对象时,只需进行类的实例化,就不需要进行类的初始化了。
2024-11-17 18:45:23 827
原创 类的加载和初始化
加载某个类指的是将该类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个该类的java.lang.Class对象(Class是java.lang包中的一个类),用来封装该类在方法区内的数据结构。类加载的最终产品是位于堆区中的Class对象。Class对象封装了类在方法区内的数据结构,并且向Java程序提供了访问方法区内数据结构的接口。加载阶段完成后,虚拟机外部的二进制字节流就按照虚拟机所需的格式存储在方法区之中,而且在Java堆中也创建一个java.lang.C
2024-11-17 18:22:33 1242
原创 JVM的各个组成部分及作用
JVM主要包括下面四部分,其中运行时数据区是JVM的主要部分。class loader 类加载器:加载类文件到内存。Class loader只管加载,只要符合文件结构就加载,至于能否运行,它不负责,那是有Execution Engine 负责的。execution engine :执行引擎也叫解释器,负责解释命令,交由操作系统执行。native interface:本地接口。本地接口的作用是融合不同的语言为java所用。
2024-11-17 18:06:40 640
原创 IO复用模型
IO多路复用、select模型、poll模型、epoll模型等知识点,常常是Java高级工程师及以上岗位在面试中遇到的必问面试题。为了讲多路复用,当然还是要跟风,采用鞭尸的思路,先讲讲传统的网络 IO 的弊端,用拉踩的方式捧起多路复用 IO 的优势。为了方便理解,以下所有代码都是伪代码,知道其表达的意思即可。
2024-11-15 22:58:19 969
原创 同步(阻塞和非阻塞)和异步IO概念
IO操作概念:在Unix系统中,一切都是文件。文件就是流的概念,在进行信息的交流过程中,对这些流进行数据的收发操作就是IO操作。我们都知道unix(like)世界里,一切皆文件,而文件是什么呢?文件就是一串二进制流而已,不管socket,还是FIFO、管道、终端,对我们来说,一切都是文件,一切都是流。在信息交换的过程中,我们都是对这些流进行数据的收发操作,简称为I/O操作(input and output),从流中读出数据,系统调用read,向流中写入数据,系统调用write。
2024-11-15 22:32:06 601
原创 CompletableFuture的简单用法
Java8中的CompletableFuture是对Future的扩展实现, 主要是为了弥补Future没有相应的回调机制的缺陷。CompletableFuture实现了Future和CompletionStage两个接口。
2024-11-14 23:35:46 699
原创 ThreadLocal原理与简单使用
什么是ThreadLocal?ThreadLocal类顾名思义可以理解为线程本地变量,也就是说,如果定义了一个ThreadLocal,每个线程往这个ThreadLocal中读写数据是线程隔离的,互相之间不会影响。它提供了一种将可变数据通过每个线程有自己的独立副本从而实现线程封闭的机制。它大致的实现思路是怎样的?Thread类有一个类型为ThreadLocal.ThreadLocalMap的实例变量threadLocals,也就是说每个线程有一个自己的ThreadLocalMap。
2024-11-11 00:02:27 1174
原创 线程池ThreadPoolExecutor
每当使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题:如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。在Java中通过线程池使线程可以复用,就是线程执行完一个任务,并不被销毁,而是可以继续执行其他的任务。线程池的种类及使用场景。
2024-11-10 22:38:32 812
原创 线程池ForkJoinPool
工作队列中保存的是等待执行的任务ForkJoinTask,是保存在数组中的,每个工作线程会优先完成自己队列中的任务,当自己队列中的任务为空时,才会通过工作窃取work-stealing算法从其他任务队列中获取任务。3.每个工作线程在处理自己的工作队列同时,会尝试窃取一个任务(或是来自于刚刚提交到 pool 的任务,或是来自于其他工作线程的工作队列),窃取的任务位于其他线程的工作队列的队首,也就是说工作线程在窃取其他工作线程的任务时,使用的是 FIFO 方式。例子:求1-100的和。
2024-11-10 21:39:23 158
原创 CountDownLatch和CyclicBarrier的区别
CountDownLatch是一个同步的辅助类,允许一个或多个线程,等待其他一组线程完成操作,再继续执行。CyclicBarrier是一个同步的辅助类,允许一组线程之间相互等待,达到一个共同点,再继续执行。CountDownLatch的计数器无法被重置;CyclicBarrier的计数器可以被重置后使用,因此它被称为是循环的barrier。他们都是:Synchronization aid,把它翻译成同步辅助器,既然是辅助工具,怎么使用?哪些场景使用?
2024-11-10 18:30:44 601
原创 乐观锁和悲观锁的实现方式
当线程A要更新数据值时,在读取数据的同时也会读取version值,在提交更新时,若刚才读取到的version值与当前数据库中的version值相等时才更新,否则重试更新操作,直到更新成功。:总是认为不会产生并发问题,每次读取数据的时候总认为不会有其他线程对数据进行修改,因此不会上锁,但是在更新数据时,会判断其他线程在这之前有没有对数据进行修改,如果其他线程对数据进行了修改,因为并发冲突而导致更新失败,该线程就会反复重试更新数据,直到成功为止。为例,看一下在不使用锁的情况下是如何保证线程安全的。
2024-11-10 18:05:59 712
原创 AbstractQueuedSynchronizer(AQS)的原理与源码分析
头节点最开始是不封装线程的,头节点中thread字段的值被默认初始化成null,只有第一个获取锁的线程释放锁之后,唤醒头节点的下一个节点中的线程去获取锁,这时头节点的下一个节点成为新的头节点,此时头节点中才有线程,而且此时头节点中的线程被设置成了null,因为当前线程已经获取到了锁,没必要再保存在同步队列中了。1.当前线程尝试获取锁,对于公平锁,首先判断同步队列中是否有线程在等待,如果有,则将当前线程添加到同步队列中,如果没有,则通过CAS操作尝试修改同步状态state的值。如果获取失败,则阻塞当前线程。
2024-11-06 23:05:51 591
原创 java同步的实现方式,以及synchronized与Lock的异同
C、tryLock(long timeout, TimeUnit timeUnit)方法:如果获取了锁定立即返回true,如果别的线程正持有锁,会等待参数给定的时间,在等待的过程中,如果获取了锁定,就返回true,如果等待超时,返回false。java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查),相互之间产生冲突,将会导致数据不准确,因此加入同步锁以避免在该线程没有完成操作之前,被其他线程的调用,从而保证了该变量的唯一性和准确性。
2024-11-06 21:59:29 910
原创 synchronized加锁原理以及锁升级过程
由于synchronized中用到了CAS技术,此处先对CAS做个简单介绍。是乐观锁技术,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败。CAS(V,A,B)操作中至少包含三个操作数——需要读写的内存位置(V)、进行比较的预期原值(A)和拟写入的新值(B)。如果内存位置V的值与预期原值A相匹配,那么处理器会自动将该位置值更新为新值B。否则处理器不做任何操作。无论哪种情况,它都会在CAS指令之前返回该位置的值。在。
2024-11-03 22:33:25 915
原创 并发和并行,守护线程和用户线程,以及线程的六种状态
创建线程之后调用线程的start()方法,或该线程调用的Thread.sleep()方法结束,或在该线程中其他线程调用的join()结束,或其他线程调用notify或notifyAll方法唤醒该线程,或该线程获取到了同步方法的锁对象,或该线程的CPU时间片用完了,或在该线程中调用Thread.yield()方法。因此,当所有的非守护线程(用户线程,就是应用程序里的自定义线程)结束时,程序也就终止了,同时会杀死进程中的所有守护线程。这个线程对象也许是活的,但是,它已经不是一个单独执行的线程。
2024-11-03 22:04:49 1024
原创 多线程之间的通讯
由于线程A和线程B持有同一个MyObject类的对象object,尽管这两个线程需要调用不同的方法,但是它们是同步执行的,假如线程A先执行methodA方法,那么线程B需要等待线程A执行完了methodA()方法之后,它才能执行methodB()方法。当条件满足时,线程B调用 notify()通知线程A,所谓通知线程A,就是唤醒线程A,让它尝试获取锁,若获取成功,则进入可运行状态,否则进入阻塞状态。因为,线程B已经发了通知了,以后不再发通知了。=5),线程A调用wait() 放弃CPU,并进入等待状态。
2024-11-03 21:32:18 746
原创 notify和notifyAll的区别,以及sleep、wait和join的区别
对象的wait(0)方法的作用是让线程一直等待,直到其他线程针对该线程调用同一个对象的notify或notifyAll方法。这是因为线程t1和线程t2的run方法中同步代码块中的锁对象都是t1对象,在线程t2的run中调用了t1.join()方法,由上面分析可知,在join方法内部,线程t2会再次获取t1对象作为锁对象进入到join方法内部的同步方法中,并在执行join方法内部的wait方法时释放掉t1对象锁,这时线程t2就不再拥有任何锁,线程t1就可以获取到锁对象t1从而执行自己的run方法。
2024-11-03 21:21:14 928
原创 interrupt、interrupted、isInterrupted方法详解
thread线程调用了interrupt方法,并没有使thread线程立即中断,只是将thread线程的中断标志设置为true(线程的中断状态被设置),通过thread.isInterrupted方法判断线程的中断状态是否被设置,若被设置了,则返回true,否则返回false。当线程调用interrupt方法时,会进入到同步代码块中,由于blocker==null,所以不执行if语句中的代码,而是调用interrupt0()方法,将线程的中断标志位设置为true。方法不能中断线程,只是设置线程的中断状态。
2024-11-03 20:30:08 582
原创 进程与线程的区别,以及创建线程的几种方式
(此处说的是线程,而不是普通对象)的wait方法,此时线程A会释放掉持有的线程B对象的锁,并等待线程B执行run方法。当线程B运行结束时,会自动调用自身的notifyAll方法,唤醒所有等待线程B对象锁的线程尝试获取锁,即线程A会被唤醒,尝试获取线程B对象的锁,如果获取成功,则接着wait方法之后的代码继续执行,如果获取失败,则进入线程B对象的锁池阻塞等待,并尝试下一次获取B对象的锁。(1)定义runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。
2024-11-03 20:20:18 770
原创 Java内存模型以及原子性、可见性与有序性
线程安全高频面试题:高并发如何保证线程安全,谈谈你对高并发的理解。其实java的多线程并发问题最终都会反映在java的内存模型上,高并发情况下需要保证线程安全,所谓线程安全无非是要控制多个线程对某个公共资源的有序访问或修改。在回答高并发的问题时,主要从java内存模型与线程同步两方面回答即可。线程安全就是说多线程访问同一代码,不会产生不确定的结果。如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。
2024-11-03 19:50:50 601
原创 迭代器 Iterator的原理以及与ListIterator的区别
3.ListIterator实现了Iterator接口,并新增了其他功能,比如:add()方法向集合中增加元素,set()方法修改集合中的元素,previousIndex()方法获取前一个元素的索引,nextIndex()方法获取后一个元素的索引等。由于每一个容器都有取出或删除元素的功能,这些功能定义都一样,只不过实现的具体方式不同(因为每一个容器的数据结构不一样),所以,在java中对共性的功能进行抽取并封装在Iterator接口中,从而出现了迭代器。一个方法,用于获取迭代器。
2024-11-03 10:48:00 369
原创 Queue中add/offer、element/peek、remove/poll区别
1. add和offer方法都是向队列中增加元素,区别在于:在队列满的情况下,add方法将选择抛异常来表示队列已经满了,而offer方法通过返回false表示队列已经满了;3. element和peek方法都是返回队列的头元素,但是不删除头元素,区别在于:在队列为空的情况下,element方法将抛异常,而peek方法将返回null。2. remove和poll方法都是删除并返回队列的头元素,区别在于:在队列为空的情况下,remove方法将抛异常,而poll方法将返回null;
2024-11-03 10:35:52 194
原创 数组和List之间的区别及转换
附上arraylist扩充机制:newCapacity=oldCapacity+(oldCapacity>>1)(注:>>1:右移1位,相当于除以2),但由于源码里传过来的minCapcatiy的值是size+1,能够实现grow方法调用就肯定是(size+1)>elementData.length的情况,所以size就是初始最大容量或上一次扩容后达到的最大容量,才会进行扩容。而且,每次添加新的元素的时候都会检查内部数组的空间是否足够,效率比数组低(这是比较麻烦的地方)。
2024-11-03 10:33:10 274
原创 ConcurrentHashMap的实现原理
在jdk1.7及之前,ConcurrentHashMap采用数组+单向链表的数据结构,在jdk1.8变更为数组+单向链表+红黑树的结构。由于HashMap是线程不安全的,如何在多线程高并发环境下安全地使用HashMap呢?那就需要考虑线程安全的Map。Hashtable、SynchronizedMap和ConcurrentHashMap都是线程安全的,他们之间有什么区别呢?
2024-11-03 10:27:51 473
原创 Java中的容器及其区别
|Collection | ├List | │-├LinkedList | │-├ArrayList | │-└Vector | │ └Stack | ├Set | │├HashSet | │├TreeSet | │└LinkedSet | |Map ├Hashtable ├HashMap └WeakHashMapJava容器类类库的用途是“持有对象”,并将其划分为两个不同的概念:1)Collection:一个独立元素的序列,这些元素都服从一条或者多
2024-11-03 10:02:15 689
原创 HashMap的实现原理
HashMap是基于哈希表的Map接口的实现。此实现提供所有可选的映射操作,并允许使用null值和null键。(除了不同步和允许使用null之外,HashMap类与Hashtable大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。值得注意的是HashMap不是线程安全的,如果想要线程安全的HashMap,可以通过Collections类的静态方法synchronizedMap获得线程安全的HashMap。在JDK1.7中,HashMap的底层是基于数组和链表来实现的
2024-11-03 10:00:00 910
原创 File类的常用方法
renameTo(File dest)如果目标文件与源文件是在同一个路径下,那么renameTo的作用是重命名, 如果目标文件与源文件不是在同一个路径下,那么renameTo的作用就是剪切,而且还不能操作文件夹。listFiles() 返回目录下的文件或者目录对象(File类实例),包含隐藏文件。delete() 删除文件或者一个空文件夹,不能删除非空文件夹,马上删除文件,返回一个布尔值。length() 获取文件的大小(字节数),如果文件不存在则返回0L,如果是文件夹也返回0L。
2024-11-03 09:59:30 304
原创 java中IO流
流的概念和作用流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。IO流的分类根据处理数据类型的不同分为:字符流和字节流根据数据流向不同分为:输入流和输出流字符流的由来:因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。非纯文本文件,不能用字符流,会导致文件格式破坏,不能正常执行字节流和字符流的区别。
2024-11-02 19:43:25 850
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人