IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 7/15:java细节知识点学习第一天 -> 正文阅读

[Java知识库]7/15:java细节知识点学习第一天

第一天知识点

Arraylist 和LinkedList区别

首先,Arraylist底层维护的是数组,而linkedlist底层维护的是链表。
都实现了list接口,但是linkedlist还实现了deque接口,可以当作队列使用!

查询

对于数组而言,进行查询是相对较快的,因为是数组是创建后,就已经分配好内存空间的。直接按下标顺序放入数据,按下标进行查找是可以直接定位到要查找的数据。
对于链表进行下标查询,它是从头开始便利,在得到数据,所以慢。但是要查询链表的第一个和最后一个数据,是非常快的,因为他底层会有两个属性,专门就是记录第一个和最后一个数据的。

增加

arraylist直接进行add,是默认将数据直接插进数组的末尾(不考虑扩容),会很快。
但是,执行直接根据下标插入(不考虑扩容),这种是慢的

arraylist.add(1,5);//这里是下标为1的位置,插入数据5

因为这里涉及到插入后,这个下标之后的数据都将往后移一位。效率变低!

对于Linkedist进行add操作,也是直接将数据插入到最后,很快,但是链表没有扩容的操作。
但是,执行直接根据下标插入

linkedlist.add(1,5);//这里是下标为1的位置,插入数据5

这里会先进行遍历找到对应的下标,这里快还是满取决于你选择的下标是不是很大。然后执行插入操作,很快,改变链表指向就行。

Arraylist 和LinkedList执行添加操作,性能不能直接比较。跟实际情况而定!

删除,修改

删除、修改都是找到相应的位置 操作方式和增加类似

HashMap的put方法

它的大体流程是,先通过key进行hash算法然后与数组长度进行与运算,得到要放入哪个数组下标下。
这时候,出现几种状况:

  1. 这个数组下标位置为空:
    若为空,则将key和value封装为node对象(1.7为entry对象,1.8为ode对象),放入该位置。

  2. 不为空
    a.在jdk1.7,会先判断是否需要扩容,不要扩容,再判断是否key重复,重复的就将value覆盖之前的值,没有重复,就根据头插法放入当前位置的链表中。
    b.在jdk1.8,先判断当前node的类型,是红黑树node还是链表node

     i. 如果是红?树Node,则将key和value封装为?个红?树节点并添加到红?树中去,在这个过 程中会判断红?树中是否存在当前key,如果存在则更新value
      ii. 如果此位置上的Node对象是链表节点,则将key和value封装为?个链表Node并通过尾插法插入到链表的最后位置去,因为是尾插法,所以需要遍历链表,在遍历链表的过程中会判断是否存在当前key,如果存在则更新value,当遍历完链表后,将新链表Node插?到链表中,插?到链表后,会看当前链表的节点个数,如果?于等于8,那么则会将该链表转成红?树 
      iii. 将key和value封装为Node插?到链表或红?树中后,再判断是否需要进?扩容,如果需要就扩容,如果不需要就结束PUT?法
    

说?下ThreadLocal

它是什么呢?

ThreadLocal是Java中所提供的线程本地存储机制,可以利?该机制将数据缓存在某个线程内部,该线 程可以在任意时刻、任意?法中获取缓存的数据
我们通常设计一个person类,有一个属性比如:

String name;

我们用了ThreadLocal类,来表述这个属性:

public class Person {
    ThreadLocal<String> name = new ThreadLocal<>();

    public String getName() {
        return this.name.get();
    }

    public void setName(String name) {
        this.name.set(name);
    }
}


ThreadLocal底层是通过ThreadLocalMap来实现的,每个Thread对象(注意不是ThreadLocal 对象)中都存在?个ThreadLocalMap,Map的key为ThreadLocal对象,Map的value为需要缓存的值

我们编写一个测试类:

import java.util.concurrent.TimeUnit;

public class Tesst {
    public static void main(String[] args) {
        Person person = new Person();

        new Thread(new Runnable() {

            @Override
            public void run() {
                person.setName("大帅哥");
                try {
                    TimeUnit.SECONDS.sleep(3); //让线程睡3秒,为了让两个线程都执行了,set属性,注入了自己的值
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() +" ==>" +person.getName());
            }
        }).start();

        new Thread(new Runnable() {

            @Override
            public void run() {
                person.setName("是我");
                try {
                    TimeUnit.SECONDS.sleep(3); //让线程睡3秒
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() +" ==>" +person.getName());
            }
        }).start();
    }
}

在这里插入图片描述

我们的测试中,对应听一个person对象,再不同的线程中设置不同的属性值,然后再从里面取出来,发现不管执行多少次,拿出来的值,就是之前我们在自己的线程里设置大的值。

因为每个线程都有自己的ThreadLocalMap,存的自己的map,key和value。 所以其他线程拿不到对方线程的数据。

对于ThreadLocal还有个问题就是内存泄露,因为当ThreadLocal对象使?完之后,应该要把设置的key,value,也就是Entry对象进?回收,但线程池中的线程不会回收,会被反复使用,?线程对象是通过强引?指向ThreadLocalMap,ThreadLocalMap也是通过强引?指向Entry对象,线程不被回收,Entry对象也就不会被回收,从?出现内存泄漏,解决办法是,在使?了 ThreadLocal对象之后,?动调?ThreadLocal的remove?法,?动清除Entry对象。

ThreadLocal经典的应?场景就是连接管理(?个线程持有?个连接,该连接对象可以在不同的?法之 间进?传递,线程之间不共享同?个连接)。

说?下JVM中,哪些是共享区,哪些可以作为gc root

堆区和?法区是所有线程共享的,栈、本地?法栈、程序计数器是每个线程独有的
在这里插入图片描述
什么是gc root,JVM在进?垃圾回收时,需要找到“垃圾”对象,也就是没有被引?的对象,但是直接 找“垃圾”对象是?较耗时的,所以反过来,先找“?垃圾”对象,也就是正常对象,那么就需要从某 些“根”开始去找,根据这些“根”的引?路径找到正常对象,?这些“根”有?个特征,就是它只会引?其他 对象,?不会被其他对象引?,例如:栈中的本地变量(方法局部变量)、?法区中的静态变量、本地?法栈中的变量、正 在运?的线程等可以作为gc root。

项目如何排查JVM问题(?)

对于还在正常运?的系统:

  1. 可以使?jmap来查看JVM中各个区域的使?情况
  2. 可以通过jstack来查看线程的运?情况,?如哪些线程阻塞、是否出现了死锁
  3. 可以通过jstat命令来查看垃圾回收的情况,特别是fullgc,如果发现fullgc?较频繁,那么就得进?调优了
  4. 通过各个命令的结果,或者jvisualvm等?具来进?分析
  5. ?先,初步猜测频繁发送fullgc的原因,如果频繁发?fullgc但是??直没有出现内存溢出,那么表示 fullgc实际上是回收了很多对象了,所以这些对象最好能在younggc过程中就直接回收掉,避免这些对 象进?到?年代,对于这种情况,就要考虑这些存活时间不?的对象是不是?较?,导致年轻代放不 下,直接进?到了?年代,尝试加?年轻代的??,如果改完之后,fullgc减少,则证明修改有效
  6. 同时,还可以找到占?CPU最多的线程,定位到具体的?法,优化这个?法的执?,看是否能避免某些 对象的创建,从?节省内存

对于已经发?了OOM(内存溢出)的系统:

  1. ?般?产系统中都会设置当系统发?了OOM时,?成当时的dump?件(-XX:+HeapDumpOnOutOfMemoryError XX:HeapDumpPath=/usr/local/base)
  2. 我们可以利?jsisualvm等?具来分析dump?件
  3. 根据dump?件找到异常的实例对象,和异常的线程(占?CPU?),定位到具体的代码
  4. 然后再进?详细的分析和调试 总之,调优不是?蹴?就的,需要分析、推理、实践、总结、再分析,最终定位到具体的问题

如何查看线程死锁(?)

  1. 可以通过jstack命令来进?查看,jstack命令中会显示发?了死锁的线程
  2. 或者两个线程去操作数据库时,数据库发?了死锁,这是可以查询数据库的死锁情况
1、查询是否锁表 
show OPEN TABLES where In_use > 0; 
2、查询进程 
show processlist;
3、查看正在锁的事务 
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS; 
4、查看等待锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;

线程之间如何进行通讯的(?)

  1. 线程之间可以通过共享内存(也就是同一个机器上)或基于?络来进?通信
  2. 如果是通过共享内存来进?通信,则需要考虑并发问题,什么时候阻塞,什么时候唤醒 像Java中的wait()、notify()就是阻塞和唤醒
  3. 通过?络就?较简单了,通过?络连接将通信数据发送给对?,当然也要考虑到并发问题,处理?式就是加锁等?式

Spring的事务是如何实现的?

Spring在不同的事务管理API之上定义了一个抽象层,使得开发人员不必了解底层的事务管理API就可以使用Spring的事务管理机制。Spring支持编程式事务管理和声明式的事务管理。
编程式事务管理:
将事务管理代码嵌到业务方法中来控制事务的提交和回滚
缺点:必须在每个事务操作业务逻辑中包含额外的事务管理代码
声明式事务管理
一般情况下比编程式事务好用。
将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。
将事务管理作为横切关注点,通过aop方法模块化。Spring中通过Spring AOP框架支持声明式事务管理。
详细实现:

<!--配置声明式事物 与编程式事物不同 编程式事务是在代码里直接try catch 这里直接改变代码不推荐 因此使用声明式事事务-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="datasouce"/>
    </bean>
<!--    结合aop实现事务织入-->
<!--    配置事务通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
<!--            给那些方法配置事务-->
            <tx:method name="getUserList"/>
            <tx:method name="add" propagation="REQUIRED"/>
            <tx:method name="delete" propagation="REQUIRED"/>
<!--            给所有的方法配置事务-->
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

<!--    配置切入点-->
    <aop:config>
        <aop:pointcut id="expoincut" expression="execution(* com.hzf.dao.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="expoincut"/>
    </aop:config>
</beans>

用这个方式开启事务,根据aop配置切入点,给所要实现事务的方法进行切入。
手动提交事务,就try catch  try'中 commit catch中 rollback

什么是事务

事务是访问数据库的一个操作序列,数据库应用系统通过事务集来完成对数据库的存取。事务的正确执行使得数据库从一种状态转换为另一种状态。 事务的作用

事务管理对于企业级应用而言至关重要,它保证了用户的每一次操作都是可靠的,即便出现了异常的访问情况,也不至于破坏后台数据的完整性。就像银行的自动提款机ATM,通常ATM都可以正常为客户服务,但是也难免遇到操作过程中及其突然出故障的情况,此时,事务就必须确保出故障前对账户的操作不生效,就像用户刚才完全没有使用过ATM机一样,以保证用户和银行的利益都不受损失。

事务的特性(*):

特征说明
原子性(A)一个事务中的所有操作,要么全都成功,要么全都不成功,不会结束在中间某个环节;
一致性(C)事务开始之前和结束之后,数据库的完整性没有被破坏;
隔离性(I)要求每个读写事务的操作对象与其他事务的操作对象能相互隔离;
持久性(D)事务一旦提交,其结果就会持久化,就算发生宕机也能恢复数据;

并发下事务会产生的问题

举个例子,事务A和事务B操纵的是同一个资源,事务A有若干个子事务,事务B也有若干个子事务,事务A和事务B在高并发的情况下,会出现各种各样的问题。“各种各样的问题”,总结一下主要就是五种:第一类丢失更新、第二类丢失更新、脏读、不可重复读、幻读。五种之中,第一类丢失更新、第二类丢失更新不重要,不讲了,讲一下脏读、不可重复读和幻读。

1、脏读

所谓脏读,就是指事务A读到了事务B还没有提交的数据,比如银行取钱,事务A开启事务,此时切换到事务B,事务B开启事务–>取走100元,此时切换回事务A,事务A读取的肯定是数据库里面的原始数据,因为事务B取走了100块钱,并没有提交,数据库里面的账务余额肯定还是原始余额,这就是脏读。

2、不可重复读

所谓不可重复读,就是指在一个事务里面读取了两次某个数据,读出来的数据不一致。还是以银行取钱为例,事务A开启事务–>查出银行卡余额为1000元,此时切换到事务B事务B开启事务–>事务B取走100元–>提交,数据库里面余额变为900元,此时切换回事务A,事务A再查一次查出账户余额为900元,这样对事务A而言,在同一个事务内两次读取账户余额数据不一致,这就是不可重复读。

3、幻读

所谓幻读,就是指在一个事务里面的操作中发现了未被操作的数据。比如学生信息,事务A开启事务–>修改所有学生当天签到状况为false,此时切换到事务B,事务B开启事务–>事务B插入了一条学生数据,此时切换回事务A,事务A提交的时候发现了一条自己没有修改过的数据,这就是幻读,就好像发生了幻觉一样。幻读出现的前提是并发的事务中有事务发生了插入、删除操作。

事务的隔离级别

在这里插入图片描述
DEFAULT
使用数据库本身使用的隔离级别
ORACLE(读已提交) MySQL(可重复读)

Read uncommitted
读未提交,顾名思义,就是一个事务可以读取另一个未提交事务的数据。

Read committed
读提交,顾名思义,就是一个事务要等另一个事务提交后才能读取数据。
解决了脏读,但不能解决不可重复读和幻读。

Repeatable read
重复读,就是在开始读取数据(事务开启)时,不再允许修改操作
解决了不可重复读,但不能解决幻读。

Serializable 序列化
==Serializable ==是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。

事务的传播机制

事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。

即:在执行一个@Transactinal注解标注的方法时,开启了事务;当该方法还在执行中时,另一个人也触发了该方法; 那么此时怎么算事务呢,这时就可以通过事务的传播机制来指定处理方式。

常量含义
TransactionDefinition.PROPAGATION_REQUIRED如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。
TransactionDefinition.PROPAGATION_REQUIRES_NEW创建一个新的事务,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_SUPPORTS如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED以非事务方式运行,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_NEVER以非事务方式运行,如果当前存在事务,则抛出异常。
TransactionDefinition.PROPAGATION_MANDATORY如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
TransactionDefinition.PROPAGATION_NESTED如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。

什么时候@Transactional失效

Transactional 注解只能应用到 public 可见度的方法上。 如果应用在protected、private或者 package可见度的方法上,也不会报错,不过事务设置不会起作用

因为Spring事务是基于代理来实现的,也就是我们加了该注解后,生成一个代理对象,被代理对象调用该方法不会起作用,所以某个加了@Transactional的?法只有是代理对象调?时,那么这个注解才会?效。
同时如果某个?法是private的,那么@Transactional也会失效,因为底层cglib也是一种代理和java的动态代理类似,但是更强大)是基于??类来实现的,因为代理生成的对象底层还会对方法进行重载 ?类是不能重载?类的private?法的,所以?法很好的利?代理,也会导致@Transactianal失效。

Jdk1.7到Jdk1.8 HashMap 发生了什么变化(底层)?

  1. 1.7中底层是数组+链表,1.8中底层是数组+链表+红?树,加红?树的?的是提?HashMap插?和查询 整体效率
  2. 1.7中链表插?使?的是头插法,1.8中链表插?使?的是尾插法,因为1.8中插?key和value时需要判断链表元素个数,所以需要遍历链表统计链表元素个数,所以正好就直接使?尾插法
  3. 1.7中哈希算法?较复杂,存在各种右移与异或运算,1.8中进?了简化,因为复杂的哈希算法的?的就是提?散列性,来提供HashMap的整体效率,?1.8中新增了红?树,所以可以适当的简化哈希算法, 节省CPU资源.

Jdk1.7到Jdk1.8 java虚拟机发生了什么变化?(?)

1.7中存在永久代,1.8中没有永久代,替换它的是元空间,元空间所占的内存不是在虚拟机内部,?是本地内存空间,这么做的原因是,不管是永久代还是元空间,他们都是?法区的具体实现,之所以元空间所占的内存改成本地内存,官?的说法是为了和JRockit统?,不过额外还有?些原因,?如?法区所存储的类信息通常是?较难确定的,所以对于?法区的??是?较难指定的,太?了容易出现?法区溢出,太?了 ?会占?了太多虚拟机的内存空间,?转移到本地内存后则不会影响虚拟机所占?的内存。

如何实现AOP,项目哪些地方用到了AOP?

AOP的底层实现原理就是动态代理模式。
可以针对某个类 ?成代理对象,当调?代理对象的某个?法时,可以任意控制该?法的执?,?如可以先打印执?时间, 再执?该?法,并且该?法执?完成后,再次打印执?时间。

AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

项目哪些地方用到了AOP?(底层运行原理还不太了解)

提供声明式事务;就是我们上面提到的spring开启事务。
允许用户自定义切面。
项?中,?如事务、权限控制、?法执?时??志都是通过AOP技术来实现的,凡是需要对某些?法做统 ?处理的都可以?AOP来实现,利?AOP可以做到业务?侵?。

springboot常用的注解?

  1. @SpringBootApplication注解:这个注解标识了?个SpringBoot?程,它实际上是另外三个注解的组 合,这三个注解是:
    a. @SpringBootConfiguration:这个注解实际就是?个@Configuration,表示启动类也是?个配置类
    b. @EnableAutoConfiguration:向Spring容器中导?了?个Selector,?来加载ClassPath下 SpringFactories中所定义的?动配置类,将这些?动加载为配置Bean
    c. @ComponentScan:标识扫描路径,因为默认是没有配置实际扫描路径,所以SpringBoot扫描的 路径是启动类所在的当前?录
  2. @Bean注解:?来定义Bean,类似于XML中的标签,Spring在启动时,会对加了@Bean注解 的?法进?解析,将?法的名字做为beanName,并通过执??法得到bean对象
  3. @Controller、@Service、@ResponseBody、@Autowired都可以说
  4. 还可以说一系列的@Enable*注解,开启一系列的功能
  5. 与redis整合,开启缓存的@EnableCaching//注解配置启用缓存
  6. @EnableTransactionManagement 开启事务(默认开启)
  7. @EnableScheduling //定时任务
  8. 与springcloud整合
    @EnableEurekaClient //在服务启动后,自动注册到Eureka中
    @EnableDiscoveryClient //服务发现
    @EnableEurekaServer //EnableEurekaServer 服务端的启动类,可以接受别人注册进来
    等等等等。。。。。。。

分布式锁及其实现(需要仔细了解)

什么是分布式锁?

我们在开发应用的时候,如果需要对某一个共享变量进行多线程同步访问的时候,可以使用我们学到的Java多线程的18般武艺进行处理,并且可以完美的运行,毫无Bug!

注意这是单机应用,也就是所有的请求都会分配到当前服务器的JVM内部,然后映射为操作系统的线程进行处理!而这个共享变量只是在这个JVM内部的一块内存空间!

后来业务发展,需要做集群,一个应用需要部署到几台机器上然后做负载均衡,大致如下图:
在这里插入图片描述
上图可以看到,变量A存在JVM1、JVM2、JVM3三个JVM内存中,如果不加任何控制的话,变量A同时都会在JVM分配一块内存,三个请求发过来同时对这个变量操作,显然结果是不对的!即使不是同时发过来,三个请求分别操作三个不同JVM内存区域的数据,变量A之间不存在共享,也不具有可见性,处理的结果也是不对的!

为了保证一个方法或属性在高并发情况下的同一时间只能被同一个线程执行,在传统单体应用单机部署的情况下,可以使用Java并发处理相关的API(如ReentrantLock或Synchronized)进行互斥控制。在单机环境中,Java中提供了很多并发处理相关的API。但是,随着业务发展的需要,原单体单机部署的系统被演化成分布式集群系统后,由于分布式系统多线程、多进程并且分布在不同机器上,这将使原单机部署情况下的并发控制锁策略失效,单纯的Java API并不能提供分布式锁的能力。为了解决这个问题就需要一种跨JVM的互斥机制来控制共享资源的访问,这就是分布式锁要解决的问题!

分布式锁应该具备哪些条件?

1、在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行; 
2、高可用的获取锁与释放锁; 
3、高性能的获取锁与释放锁; 
4、具备可重入特性; 
5、具备锁失效机制,防止死锁; 
6、具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败。

分布式锁的三种实现方式

目前几乎很多大型网站及应用都是分布式部署的,分布式场景中的数据一致性问题一直是一个比较重要的话题。分布式的CAP理论告诉我们“任何一个分布式系统都无法同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance),最多只能同时满足两项。”所以,很多系统在设计之初就要对这三者做出取舍。在互联网领域的绝大多数的场景中,都需要牺牲强一致性来换取系统的高可用性,系统往往只需要保证“最终一致性”,只要这个最终时间是在用户可以接受的范围内即可。

在很多场景中,我们为了保证数据的最终一致性,需要很多的技术方案来支持,比如分布式事务、分布式锁等。有的时候,我们需要保证一个方法在同一时间内只能被同一个线程执行。

基于数据库实现分布式锁; 
基于缓存(Redis等)实现分布式锁; 
基于Zookeeper实现分布式锁;

三种实现方式:
https://blog.csdn.net/wuzhiwei549/article/details/80692278

Redis的数据结构,及其使用场景

Redis的数据结构类型,指的是redis的值的value类型;

Redis的数据结构有:

  1. 字符串:可以?来做最简单的数据缓存,可以缓存某个简单的字符串,也可以缓存某个json格式的字符 串,Redis分布式锁的实现就利?了这种数据结构,还包括可以实现计数器、Session共享、分布式ID
  2. 哈希表:可以?来存储?些key-value对,更适合?来存储对象
  3. 列表:Redis的列表通过命令的组合,既可以当做栈,也可以当做队列来使?,可以?来缓存类似微信 公众号、微博等消息流数据
  4. 集合:和列表类似,也可以存储多个元素,但是不能重复,集合可以进?交集、并集、差集操作,从而可以实现类似,我和某?共同关注的?、朋友圈点赞等功能
  5. 有序集合:集合是?序的,有序集合可以设置顺序,可以?来实现排?榜功能

Redis集群策略(Cluster模式还不理解)

Redis提供了三种集群策略

  1. 主从模式:这种模式?较简单,主库可以读写,并且会和从库进?数据同步,这种模式下,客户端直接 连主库或某个从库,但是但主库或从库宕机后,客户端需要?动修改IP,另外,这种模式也?较难进? 扩容,整个集群所能存储的数据受到某台机器的内存容量,所以不可能?持特?数据量
  2. 哨兵模式:这种模式在主从的基础上新增了哨兵节点,但主库节点宕机后,哨兵会发现主库节点宕机, 然后在从库中选择?个库作为进的主库,另外哨兵也可以做集群,从?可以保证但某?个哨兵节点宕机 后,还有其他哨兵节点可以继续?作,这种模式可以?较好的保证Redis集群的?可?,但是仍然不能 很好的解决Redis的容量上限问题。
  3. Cluster模式:Cluster模式是?得?较多的模式,它?持多主多从,这种模式会按照key进?槽位的分配,可以使得不同的key分散到不同的主节点上,利?这种模式可以使得整个集群?持更?的数据容量,同时每个主节点可以拥有自己的多个从节点,如果该主节点宕机,会从它的从节点中选举?个新的主节点。

对于这三种模式,如果Redis要存的数据量不?,可以选择哨兵模式,如果Redis要存的数据量?,并且需要持续的扩容,那么选择Cluster模式。

关于mysql索引相关知识点

关于mysql索引,b站视频讲解

Mysql数据库中,什么情况下设置了索引但无法使用?(相关知识点不了解,去看视频)

  1. 没有符合最左前缀原则(在使用复合索引的情况下)
  2. 字段进?了隐式数据类型转化
  3. ?索引没有全表扫描效率?

https://www.bilibili.com/video/BV1W64y1u761?p=47

Innodb是如何实现事务的

利用回滚日志(undo log)重做日志(redo log)两种表实现事务,并实现 MVCC (多版本并发控制)

在执行事务的每条SQL时,会先将数据原值写入undo log 中, 然后执行SQL对数据进行修改,最后将修改后的值写入redo log中。

redo log 重做日志包括两部分:1 是内存中的重做日志缓冲 ;2 是重做日志文件。在事务提交时,必须先将该事务的所有日志写入到重做日志文件进行持久化,待事务commit操作完成才算完成。

当一个事务中的所有SQL都执行成功后,会将redo log 缓存中的数据刷入磁盘,然后提交。

如果发生回滚,会根据undo log恢复数据。

特征INNODB实现方式
原子性(A)回滚日志(undo log):用于记录数据修改前的状态;
一致性(C)重做日志(redo log):用于记录市局修改后的状态;
隔离性(I)锁:用于资源隔离,分为共享锁和排它锁;
持久性(D)重做日志(redo log) + 回滚日志(undo log);

MVCC (多版本并发控制)(还需在理解,不清楚)

查询需要对资源加共享锁(S),数据修改需要对资源加排他锁(X)

自己知道的框架使用的设计模式(仅理解代理模式,其它不清楚)

在学习?些框架或中间件的底层源码的时候遇到过?些设计模式:

  1. 代理模式:Mybatis中?到JDK动态代理来?成Mapper的代理对象,在执?代理对象的?法时会去执 ?SQL,Spring中AOP、包括@Configuration注解的底层实现也都?到了代理模式
  2. 责任链模式:Tomcat中的Pipeline实现,以及Dubbo中的Filter机制都使?了责任链模式
  3. ??模式:Spring中的BeanFactory就是?种??模式的实现
  4. 适配器模式:Spring中的Bean销毁的?命周期中?到了适配器模式,?来适配各种Bean销毁逻辑的执 ?式
  5. 外观模式:Tomcat中的Request和RequestFacade之间体现的就是外观模式
  6. 模板?法模式:Spring中的refresh?法中就提供了给?类继承重写的?法,就?到了模板?法模式

Java死锁如何避免?(加锁顺序方式?)

造成死锁的?个原因:

  1. 互斥条件:?个资源每次只能被?个线程使?
  2. 请求与保持条件: ?个线程在阻塞等待某个资源时,不释放已占有资源
  3. 不剥夺条件:?个线程已经获得的资源,在未使?完之前,不能被强?剥夺
  4. 循环等待条件:若?线程形成头尾相接的循环等待资源关系

这是造成死锁必须要达到的4个条件,如果要避免死锁,只需要不满?其中某?个条件即可。?其中前3个 条件是作为锁要符合的条件,所以要避免死锁就需要打破第4个条件,不出现循环等待锁的关系。

怎么解决循等待锁?
在开发过程中:

  1. 要注意加锁顺序,保证每个线程按同样的顺序进?加锁()
  2. 要注意加锁时限,可以针对所设置?个超时时间
  3. 要注意死锁检查,这是?种预防机制,确保在第?时间发现死锁并进?解决

解决死锁的方式?(?)

深拷贝和浅拷贝

深拷?和浅拷?就是指对象的拷?,?个对象中存在两种类型的属性,?种是基本数据类型,?种是实例 对象的引?。

  1. 浅拷?是指,只会拷?基本数据类型的值,以及实例对象的引?地址,并不会复制?份引?地址所指向 的对象,也就是浅拷?出来的对象,内部的类属性指向的是同?个对象
  2. 深拷?是指,既会拷?基本数据类型的值,也会针对实例对象的引?地址所指向的对象进?复制,深拷 ?出来的对象,内部的属性指向的不是同?个对象

如果你提交任务时,线程池队列已满,这时会发生什么?(线程的拒绝策略有???)

https://blog.csdn.net/Fly_as_tadpole/article/details/86483898

还有问题没有解决,明天先解决问题,在复习其他知识点!!!

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-07-16 11:08:15  更:2021-07-16 11:10:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/18 17:59:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码