2020-09-14

1.集合

集合14问

2.线程

  1. 并行和并发有什么区别?
    • 并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔发生。
    • 并行是在不同实体上的多个事件,并发是在同一实体上的多个事件。
    • 在一台处理器上“同时”处理多个任务,在多台处理器上同时处理多个任务。如 hadoop 分布式集
    群。
    所以并发编程的目标是充分的利用处理器的每一个核,以达到最高的处理性能。
  2. 线程和进程的区别?
    简而言之,进程是程序运行和资源分配的基本单位,一个程序至少有一个进程,一个进程至少有一个线
    程。进程在执行过程中拥有独立的内存单元,而多个线程共享内存资源,减少切换次数,从而效率更高。
    线程是进程的一个实体,是 cpu 调度和分派的基本单位,是比程序更小的能独立运行的基本单位。同一
    进程中的多个线程之间可以并发执行。
  3. 守护线程是什么?
    守护线程(即 daemon thread),是个服务线程,准确地来说就是服务其他的线程。
  4. 创建线程有哪几种方式?
    ①. 继承 Thread 类创建线程类
    • 定义 Thread 类的子类,并重写该类的 run 方法,该 run 方法的方法体就代表了线程要完成的任
    务。因此把 run()方法称为执行体。
    • 创建 Thread 子类的实例,即创建了线程对象。
    • 调用线程对象的 start()方法来启动该线程。
    ②. 通过 Runnable 接口创建线程类
    • 定义 runnable 接口的实现类,并重写该接口的 run()方法,该 run()方法的方法体同样是该线程的
    线程执行体。
    • 创建 Runnable 实现类的实例,并依此实例作为 Thread 的 target 来创建 Thread 对象,该
    Thread 对象才是真正的线程对象。
    • 调用线程对象的 start()方法来启动该线程。
    ③. 通过 Callable 和 Future 创建线程
    • 创建 Callable 接口的实现类,并实现 call()方法,该 call()方法将作为线程执行体,并且有返回值。
    • 创建 Callable 实现类的实例,使用 FutureTask 类来包装 Callable 对象,该 FutureTask 对象封装
    了该 Callable 对象的 call()方法的返回值。
    • 使用 FutureTask 对象作为 Thread 对象的 target 创建并启动新线程。
    • 调用 FutureTask 对象的 get()方法来获得子线程执行结束后的返回值。
  5. 说一下 runnable 和 callable 有什么区别?
    有点深的问题了,也看出一个 Java 程序员学习知识的广度。
    • Runnable 接口中的 run()方法的返回值是 void,它做的事情只是纯粹地去执行 run()方法中的代码
    而已;
    • Callable 接口中的 call()方法是有返回值的,是一个泛型,和 Future、FutureTask 配合可以用来获
    取异步执行的结果。
  6. 线程有哪些状态?
    线程通常都有五种状态,创建、就绪、运行、阻塞和死亡。
    • 创建状态。在生成线程对象,并没有调用该对象的 start 方法,这是线程处于创建状态。
    • 就绪状态。当调用了线程对象的 start 方法之后,该线程就进入了就绪状态,但是此时线程调度程
    序还没有把该线程设置为当前线程,此时处于就绪状态。在线程运行之后,从等待或者睡眠中回来
    之后,也会处于就绪状态。
    • 运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开
    始运行 run 函数当中的代码。
    • 阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)
    之后再继续运行。sleep,suspend,wait 等方法都可以导致线程阻塞。
    • 死亡状态。如果一个线程的 run 方法执行结束或者调用 stop 方法后,该线程就会死亡。对于已经
    死亡的线程,无法再使用 start 方法令其进入就绪
  7. sleep() 和 wait() 有什么区别?
    sleep():方法是线程类(Thread)的静态方法,让调用线程进入睡眠状态,让出执行机会给其他线程,
    等到休眠时间结束后,线程进入就绪状态和其他线程一起竞争 cpu 的执行时间。因为 sleep() 是 static
    静态的方法,他不能改变对象的机锁,当一个 synchronized 块中调用了 sleep() 方法,线程虽然进入休
    眠,但是对象的机锁没有被释放,其他线程依然无法访问这个对象。
    wait():wait()是 Object 类的方法,当一个线程执行到 wait 方法时,它就进入到一个和该对象相关的等
    待池,同时释放对象的机锁,使得其他线程能够访问,可以通过 notify,notifyAll 方法来唤醒等待的线
    程。
  8. notify()和 notifyAll()有什么区别?
    • 如果线程调用了对象的 wait()方法,那么线程便会处于该对象的等待池中,等待池中的线程不会去
    竞争该对象的锁。
    • 当有线程调用了对象的 notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个
    wait 线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。也就
    是说,调用了 notify 后只要一个线程会由等待池进入锁池,而 notifyAll 会将该对象等待池内的所
    有线程移动到锁池中,等待锁竞争。
    • 优先级高的线程竞争到对象锁的概率大,假若某线程没有竞争到该对象锁,它还会留在锁池中,唯
    有线程再次调用 wait()方法,它才会重新回到等待池中。而竞争到对象锁的线程则继续往下执行,
    直到执行完了 synchronized 代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象
    锁。
  9. 线程的 run()和 start()有什么区别?
    每个线程都是通过某个特定 Thread 对象所对应的方法 run()来完成其操作的,方法 run()称为线程体。通
    过调用 Thread 类的 start()方法来启动一个线程。
    start()方法来启动一个线程,真正实现了多线程运行。这时无需等待 run 方法体代码执行完毕,可以直接
    继续执行下面的代码; 这时此线程是处于就绪状态, 并没有运行。 然后通过此 Thread 类调用方法
    run()来完成其运行状态, 这里方法 run()称为线程体,它包含了要执行的这个线程的内容, Run 方法运
    行结束, 此线程终止。然后 CPU 再调度其它线程。
    run()方法是在本线程里的,只是线程里的一个函数,而不是多线程的。 如果直接调用 run(),其实就相当于
    是调用了一个普通函数而已,直接待用 run()方法必须等待 run()方法执行完毕才能执行下面的代码,所以
    执行路径还是只有一条,根本就没有线程的特征,所以在多线程执行时要使用 start()方法而不是 run()方
    法。
  10. 创建线程池有哪几种方式?
    ①. newFixedThreadPool(int nThreads)
    创建一个固定长度的线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程
    规模将不再变化,当线程发生未预期的错误而结束时,线程池会补充一个新的线程。
    ②. newCachedThreadPool()
    创建一个可缓存的线程池,如果线程池的规模超过了处理需求,将自动回收空闲线程,而当需求增加时,
    则可以自动添加新线程,线程池的规模不存在任何限制。
    ③. newSingleThreadExecutor()
    这是一个单线程的 Executor,它创建单个工作线程来执行任务,如果这个线程异常结束,会创建一个新
    的来替代它;它的特点是能确保依照任务在队列中的顺序来串行执行。
    ④. newScheduledThreadPool(int corePoolSize)
    创建了一个固定长度的线程池,而且以延迟或定时的方式来执行任务,类似于 Timer。
  11. 线程池都有哪些状态?
    线程池有 5 种状态:Running、ShutDown、Stop、Tidying、Terminated。
    线程池各个状态切换框架图:
  12. 线程池中 submit()和 execute()方法有什么区别?
    • 接收的参数不一样
    • submit 有返回值,而 execute 没有
    • submit 方便 Exception 处理
  13. 在 java 程序中怎么保证多线程的运行安全?
    线程安全在三个方面体现:
    • 原子性:提供互斥访问,同一时刻只能有一个线程对数据进行操作,(atomic,synchronized);
    • 可见性:一个线程对主内存的修改可以及时地被其他线程看到,(synchronized,volatile);
    • 有序性:一个线程观察其他线程中的指令执行顺序,由于指令重排序,该观察结果一般杂乱无序,
    (happens-before 原则)。
  14. 多线程锁的升级原理是什么?
    在 Java 中,锁共有 4 种状态,级别从低到高依次为:无状态锁,偏向锁,轻量级锁和重量级锁状态,这
    几个状态会随着竞争情况逐渐升级。锁可以升级但不能降级。
    锁升级的图示过程:
  15. 什么是死锁?
    死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现
    象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互
    相等待的进程称为死锁进程。是操作系统层面的一个错误,是进程死锁的简称,最早在 1965 年由
    Dijkstra 在研究银行家算法时提出的,它是计算机操作系统乃至整个并发程序设计领域最难处理的问题之
    一。
  16. 怎么防止死锁?
    死锁的四个必要条件:
    • 互斥条件:进程对所分配到的资源不允许其他进程进行访问,若其他进程访问该资源,只能等待,
    直至占有该资源的进程使用完成后释放该资源
    • 请求和保持条件:进程获得一定的资源之后,又对其他资源发出请求,但是该资源可能被其他进程
    占有,此事请求阻塞,但又对自己获得的资源保持不放
    • 不可剥夺条件:是指进程已获得的资源,在未完成使用之前,不可被剥夺,只能在使用完后自己释

    • 环路等待条件:是指进程发生死锁后,若干进程之间形成一种头尾相接的循环等待资源关系
    这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之 一不满足,
    就不会发生死锁。
    理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和 解除死锁。
    所以,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确 定资源的合理分配算
    法,避免进程永久占据系统资源。
    此外,也要防止进程在处于等待状态的情况下占用资源。因此,对资源的分配要给予合理的规划。
  17. ThreadLocal 是什么?有哪些使用场景?
    线程局部变量是局限于线程内部的变量,属于线程自身所有,不在多个线程间共享。Java 提供
    ThreadLocal 类来支持线程局部变量,是一种实现线程安全的方式。但是在管理环境下(如 web 服务
    器)使用线程局部变量的时候要特别小心,在这种情况下,工作线程的生命周期比任何应用变量的生命周
    期都要长。任何线程局部变量一旦在工作完成后没有释放,Java 应用就存在内存泄露的风险。
    52.说一下 synchronized 底层实现原理?
    synchronized 可以保证方法或者代码块在运行时,同一时刻只有一个方法可以进入到临界区,同时它还
    可以保证共享变量的内存可见性。
    Java 中每一个对象都可以作为锁,这是 synchronized 实现同步的基础:
    • 普通同步方法,锁是当前实例对象
    • 静态同步方法,锁是当前类的 class 对象
    • 同步方法块,锁是括号里面的对象
  18. synchronized 和 volatile 的区别是什么?
    • volatile 本质是在告诉 jvm 当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读
    取; synchronized 则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
    • volatile 仅能使用在变量级别;synchronized 则可以使用在变量、方法、和类级别的。
    • volatile 仅能实现变量的修改可见性,不能保证原子性;而 synchronized 则可以保证变量的修改
    可见性和原子性。
    • volatile 不会造成线程的阻塞;synchronized 可能会造成线程的阻塞。
    • volatile 标记的变量不会被编译器优化;synchronized 标记的变量可以被编译器优化。
  19. synchronized 和 Lock 有什么区别?
    • 首先 synchronized 是 java 内置关键字,在 jvm 层面,Lock 是个 java 类;
    • synchronized 无法判断是否获取锁的状态,Lock 可以判断是否获取到锁;
    • synchronized 会自动释放锁(a 线程执行完同步代码会释放锁 ;b 线程执行过程中发生异常会释放
    锁),Lock 需在 finally 中手工释放锁(unlock()方法释放锁),否则容易造成线程死锁;
    • 用 synchronized 关键字的两个线程 1 和线程 2,如果当前线程 1 获得锁,线程 2 线程等待。如果
    线程 1 阻塞,线程 2 则会一直等待下去,而 Lock 锁就不一定会等待下去,如果尝试获取不到锁,
    线程可以不用一直等待就结束了;
    • synchronized 的锁可重入、不可中断、非公平,而 Lock 锁可重入、可判断、可公平(两者皆
    可);
    • Lock 锁适合大量同步的代码的同步问题,synchronized 锁适合代码少量的同步问题。
  20. synchronized 和 ReentrantLock 区别是什么?
    synchronized 是和 if、else、for、while 一样的关键字,ReentrantLock 是类,这是二者的本质区别。
    既然 ReentrantLock 是类,那么它就提供了比 synchronized 更多更灵活的特性,可以被继承、可以有
    方法、可以有各种各样的类变量,ReentrantLock 比 synchronized 的扩展性体现在几点上:
    • ReentrantLock 可以对获取锁的等待时间进行设置,这样就避免了死锁
    • ReentrantLock 可以获取各种锁的信息
    • ReentrantLock 可以灵活地实现多路通知
    另外,二者的锁机制其实也是不一样的:ReentrantLock 底层调用的是 Unsafe 的 park 方法加锁,
    synchronized 操作的应该是对象头中 mark word。
  21. 说一下 atomic 的原理?
    Atomic 包中的类基本的特性就是在多线程环境下,当有多个线程同时对单个(包括基本类型及引用类
    型)变量进行操作时,具有排他性,即当多个线程同时对该变量的值进行更新时,仅有一个线程能成功,
    而未成功的线程可以向自旋锁一样,继续尝试,一直等到执行成功。
    Atomic 系列的类中的核心方法都会调用 unsafe 类中的几个本地方法。我们需要先知道一个东西就是
    Unsafe 类,全名为:sun.misc.Unsafe,这个类包含了大量的对 C 代码的操作,包括很多直接内存分配
    以及原子操作的调用,而它之所以标记为非安全的,是告诉你这个里面大量的方法调用都会存在安全隐
    患,需要小心使用,否则会导致严重的后果,例如在通过 unsafe 分配内存的时候,如果自己指定某些区
    域可能会导致一些类似 C++一样的指针越界到其他进程的问题。

3.mysql

索引失效情况

1.对于创建的多列索引(复合索引),不是使用的第一部分就不会使用索引

alter table student add index my_index(name, age) // name左边的列, age 右边的列

select * from student where name = ‘aaa’ // 会用到索引

select * from student where age = 18 // 不会使用索引

2.对于使用 like 查询, 查询如果是 ‘%aaa’ 不会使用索引,而 ‘aaa%’ 会使用到索引。

select * from student where name like ‘aaa%’ // 会用到索引

select * from student where name like ‘%aaa’ 或者 ‘_aaa’ // 不会使用索引

3.如果条件中有 or, 有条件没有使用索引,即使其中有条件带索引也不会使用,换言之, 就是要求使用的所有字段,都必须单独使用时能使用索引。

4.如果列类型是字符串,那么一定要在条件中使用引号引用起来,否则不使用索引。

5.如果mysql认为全表扫面要比使用索引快,则不使用索引。

扫描二维码关注公众号,回复: 11667361 查看本文章

如:表里只有一条数据。

索引是不是越多越好

1.首先数据量小的表不需要建立索引,因为小的表即使建立索引也不会有大的用处,还会增加额外的索引开销
2 不经常引用的列不要建立索引,因为不常用,即使建立了索引也没有多大意义
3 经常频繁更新的列不要建立索引,因为肯定会影响插入或更新的效率
4 索引并不是一劳永逸的,用的时间长了需要进行整理或者重建

mysql优化

8种优化方案

4.SSM

Spring通过DI(依赖注入)实现IOC(控制反转),常用的注入方式主要有三种:构造方法注入,setter注入,基于注解的注入。

mybatis常用标签

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/KI1102/article/details/108571752