<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[osillto的博客]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/osillto</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; osillto]]></copyright><item><title><![CDATA[IO复用模型]]></title><link>https://blog.youkuaiyun.com/osillto/article/details/120105376</link><guid>https://blog.youkuaiyun.com/osillto/article/details/120105376</guid><author>osillto</author><pubDate>Sat, 04 Sep 2021 20:39:58 +0800</pubDate><description><![CDATA[进程与线程的描述

一个进程至少会创建一个线程，多个线程共享一个程序进程的内存。程序的运行最终是靠线程来完成操作的。线程的数量跟CPU核数有关，一个核最多能发出两个线程。线程的操作主要分为：一：给CPU进行程序命令的执行。二：IO的操作（读取或输出数据）或者请求网络数据。

IO复用形成原因

如果一个I/O流进来，我们就开启一个进程处理这个I/O流。那么假设现在有一百万个I/O流进来，那我们就需要开启一百万个进程一一对应处理这些I/O流（——这就是传统意义下的多进程并发处理）。思考一下，一百万个进程，你的]]></description><category></category></item><item><title><![CDATA[数据库大表优化]]></title><link>https://blog.youkuaiyun.com/osillto/article/details/120034284</link><guid>https://blog.youkuaiyun.com/osillto/article/details/120034284</guid><author>osillto</author><pubDate>Sat, 04 Sep 2021 16:22:23 +0800</pubDate><description><![CDATA[1.HasMap基础


key-value形式

用key做hash定位 整个将k和v存储到对应位置

2.解决hash冲突方法
拉链法

开放地址法

3.jdk1.7和1.8的区别
1.7

头插法

hash()-&gt;4次扰动

先扩容再插入

数组+链表

1.8

尾插法

hash()-&gt;1次扰动

数组+链表/红黑树

当前链表长度&gt;=8 数组长度&gt;64

先插入再扩容

4. jdk1.8HashMap插入原理
判断数组是否为空，为空进行初始化;

不为空的，计算插入]]></description><category></category></item><item><title><![CDATA[java的动态绑定]]></title><link>https://blog.youkuaiyun.com/osillto/article/details/119972525</link><guid>https://blog.youkuaiyun.com/osillto/article/details/119972525</guid><author>osillto</author><pubDate>Sat, 28 Aug 2021 20:12:17 +0800</pubDate><description><![CDATA[Java的动态绑定又称为运行时绑定。即在程序运行过程中，根据具体的实例对象才能具体确定是哪个方法。 意思就是说，程序会在运行的时候自动选择调用那个方法。

二、Demo

　　1. 子类重写父类中的方法，调用子类中的方法


public class Father{
    public void method(){
        System.out.println("父类方法："+this.getClass());
    }
}
public class Son extends Father{
  ]]></description><category></category></item><item><title><![CDATA[java中的包装类型]]></title><link>https://blog.youkuaiyun.com/osillto/article/details/119972280</link><guid>https://blog.youkuaiyun.com/osillto/article/details/119972280</guid><author>osillto</author><pubDate>Sat, 28 Aug 2021 19:48:29 +0800</pubDate><description><![CDATA[包装类型
Java语言是一个面向对象的语言，但是Java中的基本数据类型却是不面向对象的，这在实际使用时存在很多的不便，为了解决这个不足，在设计类时为每个基本数据类型设计了一个对应的类进行代表，这样八个和基本数据类型对应的类统称为包装类(Wrapper Class)。

包装类均位于java.lang包，包装类和基本数据类型的对应关系如下表所示

基本数据类型
			包装类
		byte
			Byte
		boolean
			Boolean
		short
			Short
		char
			Char]]></description><category></category></item><item><title><![CDATA[最大子序和]]></title><link>https://blog.youkuaiyun.com/osillto/article/details/119878363</link><guid>https://blog.youkuaiyun.com/osillto/article/details/119878363</guid><author>osillto</author><pubDate>Mon, 23 Aug 2021 21:52:37 +0800</pubDate><description><![CDATA[给定一个整数数组 nums，找到一个具有最大和的连续子数组（子数组最少包含一个元素），返回其最大和。



示例 1：

输入：nums = [-2,1,-3,4,-1,2,1,-5,4]
输出：6
解释：连续子数组[4,-1,2,1] 的和最大，为6 。

来源：力扣（LeetCode）

几个连续数字相加越来越大，首先能想到一种情况全是正数，但是题中正负都有，所以在加之前要判断一次，前面几个数加上新的数字起来有没有新数字大，我们知道只有越加越大的情况下才能出现最大值，所以这里就利用了这一点，如果越...]]></description><category></category></item><item><title><![CDATA[volatile关键字]]></title><link>https://blog.youkuaiyun.com/osillto/article/details/119835961</link><guid>https://blog.youkuaiyun.com/osillto/article/details/119835961</guid><author>osillto</author><pubDate>Sat, 21 Aug 2021 10:16:39 +0800</pubDate><description><![CDATA[可见性

第一：使用volatile关键字会强制将修改的值立即写入主存；

第二：使用volatile关键字的话，当线程2进行修改时，会导致线程1的工作内存中缓存变量stop的缓存行无效（反映到硬件层的话，就是CPU的L1或者L2缓存中对应的缓存行无效）；

第三：由于线程1的工作内存中缓存变量stop的缓存行无效，所以线程1再次读取变量stop的值时会去主存读取。

那么在线程2修改stop值时（当然这里包括2个操作，修改线程2工作内存中的值，然后将修改后的值写入内存），会使得线程1的工作内存中缓存变量s]]></description><category></category></item><item><title><![CDATA[锁的升级过程]]></title><link>https://blog.youkuaiyun.com/osillto/article/details/119832309</link><guid>https://blog.youkuaiyun.com/osillto/article/details/119832309</guid><author>osillto</author><pubDate>Sat, 21 Aug 2021 10:06:38 +0800</pubDate><description><![CDATA[HotSpot的作者经过研究发现，大多数情况下，锁不仅不存在多线程竞争，而且总是由同 

一线程多次获得，为了让线程获得锁的代价更低而引入了偏向锁。当一个线程访问同步块并 

获取锁时，会在对象头和栈帧中的锁记录里存储锁偏向的线程ID，以后该线程在进入和退出 

同步块时不需要进行CAS操作来加锁和解锁，只需简单地测试一下对象头的Mark Word里是否 

存储着指向当前线程的偏向锁。如果测试成功，表示线程已经获得了锁。如果测试失败，则需 

要再测试一下Mark Word中偏向锁的标识是否设置成1（..]]></description><category></category></item><item><title><![CDATA[java中的对象结构]]></title><link>https://blog.youkuaiyun.com/osillto/article/details/119832024</link><guid>https://blog.youkuaiyun.com/osillto/article/details/119832024</guid><author>osillto</author><pubDate>Fri, 20 Aug 2021 21:55:42 +0800</pubDate><description><![CDATA[这一张图就很好的解释了java底层中对象的存储结构，MarkWord用来表示锁的情况，MetaData指向的就是元空间中加载的类的地址，数组长度是数组对象采用的，下面是实例数据

对象头
HotSpot虚拟机对象的对象头部分包括两类信息:

第一类是用于存储对象自身的运行时数据，如哈希码（HashCode）、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等，官方称它为“Mark Word”。
第二类类型指针
2.2实例数据
​ 实例数据部分是对象真正存储的有效信息，即我们在程序代码里面..]]></description><category></category></item><item><title><![CDATA[synchronized底层分析]]></title><link>https://blog.youkuaiyun.com/osillto/article/details/119831236</link><guid>https://blog.youkuaiyun.com/osillto/article/details/119831236</guid><author>osillto</author><pubDate>Fri, 20 Aug 2021 21:32:48 +0800</pubDate><description><![CDATA[首先严格来说synchronized不是真正的锁，他更像是一个加锁的操作，真正的锁是Monitor，它是属于jvm创建的一个c++的对象。

首先要看一下monitor的内部结构









底层将等待的线程加入到等待队列中，因此来保证原子性的操作，进入synchronized的必须是同一个对象，不加synchronized的对象不会关联Monitor其实在对象头里面存的重量级锁指针指向的就是monitor。


JVM基于进入和退出Monitor对 象来实现方法同步和代码块同步，但两者的实现细节不一]]></description><category></category></item><item><title><![CDATA[.java运行常见的异常]]></title><link>https://blog.youkuaiyun.com/osillto/article/details/119812956</link><guid>https://blog.youkuaiyun.com/osillto/article/details/119812956</guid><author>osillto</author><pubDate>Thu, 19 Aug 2021 22:56:49 +0800</pubDate><description><![CDATA[java提供了两种异常机制。一种是运行时异常，一种是检查式异常

检查式异常：我们经常遇到的IO异常及sql异常就属于检查式异常。对于这种异常，java编译器要求我们必须对出现的这些异常进行catch 所以 面对这种异常不管我们是否愿意，只能自己去写一堆catch来捕捉这些异常。

运行时异常：我们可以不处理。当出现这样的异常时，总是由虚拟机接管。比如：我们从来没有人去处理过NullPointerException异常，它就是运行时异常，并且这种异常还是最常见的异常之一。

throwable


	err]]></description><category></category></item><item><title><![CDATA[抽象类和接口的区别]]></title><link>https://blog.youkuaiyun.com/osillto/article/details/119812786</link><guid>https://blog.youkuaiyun.com/osillto/article/details/119812786</guid><author>osillto</author><pubDate>Thu, 19 Aug 2021 22:43:25 +0800</pubDate><description><![CDATA[抽象类出现的根本原因：无法完整描述一个事物的类

抽象类有一个特征，其抽象方法，必须在子类重写（子类非抽象类），所以，当我们父类的方法，必须要子类重写实现时，用抽象类。如上面的 goToClass() 方法，学生、老师去课堂的目的完全不同，必须自己实现。

（1）一个类中有抽象方法，这个类就变成了抽象类。 （2）抽象类中class的前面必须有abstract修饰符。 （3）抽象类中可以有普通方法，也可以有抽象方法，而抽象方法的个数可以是0个，也可以是多个。 （4）子类继承父类，必须重写全部的抽象方法，除非这]]></description><category></category></item><item><title><![CDATA[封装、继承、多态]]></title><link>https://blog.youkuaiyun.com/osillto/article/details/119811311</link><guid>https://blog.youkuaiyun.com/osillto/article/details/119811311</guid><author>osillto</author><pubDate>Thu, 19 Aug 2021 22:39:19 +0800</pubDate><description><![CDATA[面向过程注重过程，就是要分析出解决问题需要的步骤，然后按步骤一步一步实现，类调用时需要实例化，开销比较大，性能比面向对象高

面向对象最主要的就是把构成问题的事务分解成各个对象，把对象封装成方法，然后调用方法，优点就是易维护，易扩展，提高了可重用性。


	封装就是将一个对象的属性隐藏起来，不允许外界直接访问，但是可以通过调用指定的方法进行访问(name域只能通过,get set方法访问)
	
	
	继承就是子类继承父类的所有的方法，而且可以拥有自己的方法，提高了代码的重用(对扩展是开放的)
	
	
	多态]]></description><category></category></item><item><title><![CDATA[反射的优缺点]]></title><link>https://blog.youkuaiyun.com/osillto/article/details/119811207</link><guid>https://blog.youkuaiyun.com/osillto/article/details/119811207</guid><author>osillto</author><pubDate>Thu, 19 Aug 2021 21:16:36 +0800</pubDate><description><![CDATA[Java反射是一种能够在程序运行时动态访问、修改某个类中任意属性（状态）和方法（行为）的机制（包括private实例和方法），java反射机制提供了以下几个功能：在运行时判断任意一个对象所属的类；在运行时构造任意一个类的对象；在运行时判断任意一个类所具有的成员变量和方法；在运行时调用任意一个对象的方法。

反射的优点：

反射提高了程序的灵活性和扩展性，降低耦合性，提高自适应能力。它允许程序创建和控制任何类的对象，无需提前硬编码目标类

反射的缺点



1.性能问题

使用反射基本上是一种解释操作，用于字]]></description><category></category></item><item><title><![CDATA[哈夫曼树分析]]></title><link>https://blog.youkuaiyun.com/osillto/article/details/119794635</link><guid>https://blog.youkuaiyun.com/osillto/article/details/119794635</guid><author>osillto</author><pubDate>Thu, 19 Aug 2021 09:57:05 +0800</pubDate><description><![CDATA[给定N个权值作为N个叶子节点，构造一棵二叉树，若该树的带权路径长度达到最小，称这样的二叉树为最优二叉树，也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树，权值较大的结点离根较近。

这是百度搜素给的定义，从严格意义上来说哈夫曼树并不是二叉的而是多叉的，二叉树只是一种形式也是最常见的形式。这一点在百度搜素中也有注明，只是需要做一下调整，构造哈夫曼树的思想是每次选k个权重最小的元素来合成一个新的元素，该元素权重为k个元素权重之和。但是当k大于2时，按照这个步骤做下去可能到最后剩下的元素]]></description><category></category></item><item><title><![CDATA[填充每个节点的下一个右侧节点指针 II]]></title><link>https://blog.youkuaiyun.com/osillto/article/details/119788408</link><guid>https://blog.youkuaiyun.com/osillto/article/details/119788408</guid><author>osillto</author><pubDate>Wed, 18 Aug 2021 20:43:34 +0800</pubDate><description><![CDATA[给定一个二叉树

struct Node {
 int val;
 Node *left;
 Node *right;
 Node *next;
}
填充它的每个 next 指针，让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点，则将 next 指针设置为 NULL。

初始状态下，所有next 指针都被设置为 NULL。



进阶：

你只能使用常量级额外空间。
使用递归解题也符合要求，本题中递归程序占用的栈空间不算做额外的空间复杂度。


示例：





输入：root = [...]]></description><category></category></item><item><title><![CDATA[省份数量(深度优先算法)]]></title><link>https://blog.youkuaiyun.com/osillto/article/details/119765261</link><guid>https://blog.youkuaiyun.com/osillto/article/details/119765261</guid><author>osillto</author><pubDate>Tue, 17 Aug 2021 20:36:19 +0800</pubDate><description><![CDATA[有 n 个城市，其中一些彼此相连，另一些没有相连。如果城市 a 与城市 b 直接相连，且城市 b 与城市 c 直接相连，那么城市 a 与城市 c 间接相连。

省份 是一组直接或间接相连的城市，组内不含其他没有相连的城市。

给你一个 n x n 的矩阵 isConnected ，其中 isConnected[i][j] = 1 表示第 i 个城市和第 j 个城市直接相连，而 isConnected[i][j] = 0 表示二者不直接相连。

返回矩阵中 省份 的数量。



示例 1：






输入.]]></description><category></category></item><item><title><![CDATA[二叉搜索树的后序遍历序列]]></title><link>https://blog.youkuaiyun.com/osillto/article/details/119747640</link><guid>https://blog.youkuaiyun.com/osillto/article/details/119747640</guid><author>osillto</author><pubDate>Tue, 17 Aug 2021 09:00:14 +0800</pubDate><description><![CDATA[输入一个整数数组，判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回true，否则返回false。假设输入的数组的任意两个数字都互不相同。



参考以下这颗二叉搜索树：

  5
  / \
 2  6
 / \
1  3
示例 1：

输入: [1,6,3,2,5]
输出: false
示例 2：

输入: [1,3,2,6,5]
输出: true


来源：力扣（LeetCode）

这个是参照Krahets和失火的夏天两位大佬的解题思路
我们先来画一个节点多一些的二...]]></description><category></category></item><item><title><![CDATA[final、finally和finalize]]></title><link>https://blog.youkuaiyun.com/osillto/article/details/119720416</link><guid>https://blog.youkuaiyun.com/osillto/article/details/119720416</guid><author>osillto</author><pubDate>Sun, 15 Aug 2021 21:45:58 +0800</pubDate><description><![CDATA[这三个单词长得很像，但是我们知道JavaScript和Java没有任何关系，所以长得像不一定有联系。接下分析一下它们到底都是什么究极有没有联系。

final

在Java中，final关键字可以用来修饰类、方法和变量（包括成员变量和局部变量）

修饰类的时候

当用final修饰一个类时，表明这个类不能被继承。也就是说，如果一个类你永远不会让他被继承，就可以用final进行修饰。final类中的成员变量可以根据需要设为final，但是要注意final类中的所有成员方法都会被隐式地指定为final方法。

]]></description><category></category></item><item><title><![CDATA[盛最多水的容器]]></title><link>https://blog.youkuaiyun.com/osillto/article/details/119706297</link><guid>https://blog.youkuaiyun.com/osillto/article/details/119706297</guid><author>osillto</author><pubDate>Sat, 14 Aug 2021 21:38:13 +0800</pubDate><description><![CDATA[给你 n 个非负整数 a1，a2，...，an，每个数代表坐标中的一个点(i,ai) 。在坐标内画 n 条垂直线，垂直线 i的两个端点分别为(i,ai) 和 (i, 0) 。找出其中的两条线，使得它们与x轴共同构成的容器可以容纳最多的水。

说明：你不能倾斜容器。



示例 1：

输入：[1,8,6,2,5,4,8,3,7]
输出：49
解释：图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下，容器能够容纳水（表示为蓝色部分）的最大值为49。

来源：力扣（Le...]]></description><category></category></item><item><title><![CDATA[三数之和等于零]]></title><link>https://blog.youkuaiyun.com/osillto/article/details/119684868</link><guid>https://blog.youkuaiyun.com/osillto/article/details/119684868</guid><author>osillto</author><pubDate>Fri, 13 Aug 2021 22:26:54 +0800</pubDate><description><![CDATA[给你一个包含 n 个整数的数组nums，判断nums中是否存在三个元素 a，b，c ，使得a + b + c = 0 ？请你找出所有和为 0 且不重复的三元组。

注意：答案中不可以包含重复的三元组。



示例 1：

输入：nums = [-1,0,1,2,-1,-4]
输出：[[-1,-1,2],[-1,0,1]]
示例 2：

输入：nums = []
输出：[]
示例 3：

输入：nums = [0]
输出：[]

来源：力扣（LeetCode）

因为求三个数的和，所以直接多个循环使用...]]></description><category></category></item></channel></rss>