java面试准备15
Posted 清和与九
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java面试准备15相关的知识,希望对你有一定的参考价值。
sleep与wait区别
(1)对于sleep()方法,我们首先应该知道该方法是属于Thread类中的。而wait()方法,则是属于Object类的。
(2)sleep()方法导致了程序暂停执行,让出cpu给其他线程,但是他的监控状态依然保持,当指定的时间到了又会自动恢复运行状态。
(3)在调用sleep()方法的过程中,线程不会释放对象锁。
(4)当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。
start与run的区别
(1)start()方法用来启动线程,真正实现了多线程运行。这时无需等待run方法体代码执行完毕,可以继续执行下面的代码。
(2)通过调用Thread类的start()方法来启动一个线程,此时线程处于就绪态,并没有运行。
(3)方法run()称为线程体,它包含了要执行的这个线程的内容,线程就进入了运行状态,开始运行run函数中的代码。Run方法运行结束,此线程终止。然后CPU再调度其他线程。
Java后台线程
(1)定义:守护线程也称为服务线程,他是后台线程,它有一个特性,即为用户线程提供公共服务,在没有用户线程可服务时会自动离开。
(2)优先级:守护线程的优先级较低,用于为系统中的其它对象和线程提供服务。
(3)设置:通过setDamon(true)来设置线程为守护线程;将一个用户线程设置为守护线程的方式是在线程对象创建前用线程对象的setDaemon方法。
(4)在守护线程中产生的新线程也是Daemon的。
(5)生命周期:守护进程是运行在后台的一种特殊进程。它独立于控制中端并且周期性地执行某种任务或者等待处理某些发生的事件。当JVM中所有的线程都是守护线程的时候,JVM就退出了;如果还有一个以上的非守护线程JVM就不会退出。
乐观锁
乐观锁认为读多写少,遇到并发的可能性较低,每次去拿数据都认为别人不会修改,因此不会上锁。但是在更新时判断别人有没有更新这个数据,采取在写时先读出当前版本号,然后加锁操作(比较跟上一次的版本号,如果一样则更新),如果失败则要重复读-比较-写的操作。
java中的乐观锁基本都是通过CAS操作实现的,CAS是一种更新的原子操作,比较当前值与传入值是否一样,一样则更新,否则失败。
悲观锁
悲观锁认为写操作比较多,遇到并发写的操作较多,每次去拿数据都认为别人会修改,所以每次在读写数据时都会上锁,这样别人想读写这个这个数据就会被阻塞,知道拿到锁。Java中的悲观锁就是Synchronized。
自旋锁
自旋锁的原理非常简单,如果持有锁的线程能在很短时间内释放资源,那么哪些等待竞争锁的线程就不需要内核态和用户态之间的切换进入阻塞挂起状态。它们只需要等一等(自旋锁),等持有锁的线程释放锁后就可以立即获得锁,这样可以避免用户线程和内核的切换的消耗。
线程自旋是要消耗cpu的,说白了就是让cpu在做无用功,如果一直获取不到锁,那么线程也不能一直占用cpu自旋做无用功,所以需要设置一个最大自旋时间。如果持有锁的线程执行的时间超过自旋等待的最大时间扔没有释放锁,就会导致其它争用锁的线程在最大等待时间内还是获取不到锁,这时争用线程会停止自旋进入阻塞状态。
Java线程阻塞的代价
java线程是映射到操作系统原生线程之上的,如果要阻塞或者唤醒一个线程就需要操作系统介入,需要在用户态和核心态之间切换,这样的切换会消耗大量的系统资源,因为用户态与内核态都有各自专用的内存空间,用户态切换至内核态需要传递许多变量、参数给内核,内核也需要保护好用户态在切换时的一些寄存器值、变量等,以便于内核态调用结束后切换回用户态继续工作。
公平锁与非公平锁
公平锁:加锁前检查是否有排队等待的线程,优先排队等待的线程,先来先得。
非公平锁:加锁时不考虑排队等待问题,直接尝试获取锁,获取不到自动到队尾等待。
(1)非公平锁的性能比公平锁性能高5-10倍,因为公平锁需要在多核的情况下位于一个队列。
(2)Java中的Synchronized是非公平锁,ReentrantLock默认的lock()方法采用的是非公平锁。
ReadWriteLock 读写锁
为了提高性能,Java提供了读写锁,在读的地方使用读锁,在写的地方使用写锁,如果没有写锁的情况下,读是无阻塞的,在一定程度上提高了程序的执行效率。读写锁分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥。
共享锁和独占锁
独占锁:独占锁模式下,每次只能有一个线程持有锁,ReentrantLock就是以独占方式实现的互斥锁。独占锁是一种悲观的加锁策略,如果某个只读线程获取锁,则其他线程都只能等待,这种情况下就限制了不必要的并发性,因为读操作并不会影响数据的一致性。
共享锁:允许多个线程同时获得锁,并发访问资源,共享锁是一种乐观锁。
Java面试准备基础篇
以上是关于java面试准备15的主要内容,如果未能解决你的问题,请参考以下文章