1.synchronized的实现原理以及锁优化?
答:synchronized作用于方法或者代码块.保证被修饰的代码在同一时间只能别一个线程访问,
Synchronized修饰代码块时,JVM采用 montorenter、montiorexit两个指令来实现同步
Synchronized修饰同步方法时,jvm采用ACC_SYNCHRONIZED标记符来实现同步montiorienter
montiorexit或者 ACC_SYNCHRONIZED都时基于Monitor实现的实例对象里的对象头,对象头里面有mark word ,mark word指针执行了Monitor,Monitor是一种同步工具.也可以是说是一种同步机制
在java虚拟机中,.monitor是由objectMonitor实现的.objectMonitor体现出 monitor 的机制
2.简述并行和并发有什么区别?
并发 和并行是:
1.并行是指两个或者多个时间在同一时刻发生;而并发是指两个或多个时间在同一时间 间隔发生
2.并行是不同实体上的多个事件,并发是同一实体上的多个事件
3.在一台处理器上 同时 处理多个任务.在多态处理器上同时处理多个任务。例如 hadoop集群
所以 并发编程的目标是充分利用处理器的每一个核,以达到最高的处理性能
3.简述线程和进程的区别?
1.性质不同
进程是计算机中的程序,关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础
线程:是操作系统能够运行计算的最小单位.它被包含在进程中.是进程中的实际运作单位
2.适用范围不同
使用进程目的是在于清晰地刻画动态系统的内在规律.有效管理和调度进入计算机系统主存储器运行的程序
线程是为操作系统内核调度的内核资源.例如在win32线程中.由用户进程字形调度的用户线程,如linux凭条的posix Thread 或者由内核与用户进程.如win7的线程.进行混合调度
4.简述守护进程是什么?
守护进程是运行在后台的一种特殊程序.它独立于控制终端并且周期性执行某种任务或等待处理某些发生的事件.在java中垃圾回收线程就是特殊的守护进程
5.多线程的实现方式?
1.继承Thread重写run方法
2.实现runnable接口
3.实现Calltable接口
6.线程有哪些状态?
NEW 尚未启动
RUNNABLE正在执行中
BLOCKED阻塞的(被同步锁或者IO锁阻塞)
WAITIJNG永久等待状态
TIMED_WAITING 等待指定的时间重新被唤醒的状态
TERMINATED 执行完成
7.Runnable和callable有什么区别?
Runnable没有返回值
Calltable可以拿到有返回值
Callable可以看做是 runnable的补充
8.Sleep()和wait()有什么区别?
类的不同:sleep()来自Thread,wait()来自object
释放锁: sleep()不会去释放锁.wait()会释放锁
用法不同:sleep()时间到时会自动恢复.wait()可以调用 notify()/nitifyAll直接唤醒
9.Notify()和notifyAll有什么区别?
NitifyALL()会唤醒所有的线程,notify()只能唤醒一个线程。
NotifyAll()调动之后,会将全部线程由等待线程池移到锁池.然后参与锁的竞争,竞争成功 则继续执行,如果不成功则留在锁池等待锁被释放后再次参与竞争。而notify()智慧唤 醒一个线程.具体唤醒那一个线程由虚拟机进行控制
10线程的run()和start()有什么区别?
Start()方法用于启动线程
Run()方法用于执行线程时代码,
Run()可以重复使用,而start()只能调用一次
10.简述创建线程池有哪几种方式?
七种
NewsingleThreadExecutor():特点在于工作线程数据被控制为1,操作一个无界的工作队 列,所以它保证了所有的人讹误都是被顺序执行.做多有一个任务处于活动态度.并且不 允许使用者改变线程池实例.因此可以避免其改变线程数目
NewCachedThreadPool():它是一种用来处理大量短时间工作任务的线程池.具体几个特 点:它会视图缓存线程并重用.当无缓存线程可用时.就会创建新的工作线程.如果线程内 置的时间超过60秒.则被终止并移出缓存.长时间闲置时,这种线程池.不会消耗什么资源。 内部使用sychronousQueue作为工作队列
NewFixedThreadPool(int nThreads):重用指定数据(nThread)的线程.其背后使用的是无界 的工作队列.任何时候最多有nThreads个工作线程是活动的。意味着,如果任务数目超过 了活动队列的数据.将在工作队列中等待空线程的出现..如果存在工作线程退出,将会有 新的工作线程被创建.以补足指定数目的nThreads;
NewSingleThreadSecheduledExecutor()创建单线程池,返回ScheduleExecuterService可以 进行定时或周期性的工作调度
NewScheduledThreadPool(int corePoolSize):和NewSingleThreadSecheduledExecutor()类似, 创建的是个ScheduleExecuterService。可以金心血管定时或周期性的工作调度.区别在于 当以工作线程还是多个工作线程
NewWorkStrealingPool(int parallelism):这是一个经常别忽略的线程池,从java8开始加入, 这个创建方法.内部会构建frokjoinpool,利用work-strealing算法,并行的处理任务.不保 证处理顺序
ThreadPoolEXecutor():是原始的线程池创建.上面1-3方法都是对它的封装
12.简述线程池的状态?
Running:是正常的状态.接受新的任务.处理等待队列中的任务
Shutdown:不接受新的任务提交,但是会继续处理等待队列中的任务
Stop: 不接受新的任务提交.不再处理等待队列中的任务,中断正在执行任务中的线程
Tidying:所有的任务都摧毁了.workcount为0,线程池状态在转换为TidYing状态时,会执行 钩子方法terminated()
TerMinaTed:terminated()方法结束后.线程池的状态就会变成这个
13.线程池中submit()和execute()方法有什么区别?
Execute():只能执行Runnable类型的任务
Submit()可以执行Runnable和Callable类型的任务
Callable类型的任务可以获取执行返回值.而Runnable执行 无返回值
14.在java程序中怎么保证多线程的运行安全?
方式一:使用安全类.比如java.util.concurrent下的类
方式二:使用自动锁synchronized
方式三:使用手动锁Lock
15.简述什么是死锁?
当线程A持有独占锁a,并尝试去获取独占锁b的同时,线程B持有独占锁b,并尝试获 取独占锁a的情况下.就会发生AB两个线程由于互相持有对方需要的锁,而发生的阻塞 现象,我们称为死锁
16.简述如何防止死锁?
尽量使用tryLock(long timeout,timeUnit unit)的方法(ReentrantLock ReentrantReadWriteLock),设置超时时间.超时可以退出防止死锁
尽量使用java.util.concurrent并发类代替自己手写锁
尽量降低锁的使用粒度.
尽量不要几个功能同用一把锁
尽量减少同步的代码块
17.Synchronized和Lock有什么区别?
Synchronized可以给类、方法、代码块加锁;而lock只能给代码块加锁
Synchronized不需要手动获取锁和释放锁,使用简单,发生异常会自动释放锁.不会造成 死锁;而lock需要自己加锁和释放锁,如果使用不当没有unlock()去释放锁,就会造成死 锁
通过lock可以知道有没有成功获取锁,而synchronized缺没有办法获取
18.Synchronized和ReentrantLock区别是什么?
Synchronized早期的实现比较低效,对比ReentrantLock,大多数场景性能相差较大.
主要区别:
ReentrantLock使用起来比较灵活,但是必须有释放锁的配合动作
ReentrantLock必须手动获取和释放锁.而synchronized不需要手动释放和开启锁
ReentrantLock只适用于代码块锁,而synchronized可用于修饰方法、代码块等
19.说一下atomic的原理?
Atomic主要利用CAS(Compare And Wwap)和volatile和native方法来保证原子操作.从而 避免synchronized的高开销.执行效率会大大提升
20.简述什么是反射?
反射就是动态加载对象.并对对象进行剖析。在运行状态中.对于任意一个类.都能够只掉 这个类的所有属性和方法;对于任意一个你对象.都能调用它的任意一个方法,这种动 态获取信息以及动态调用对象方法的功能称为java反射机制
21.简述反射的优缺点?
优点:
反射提高了程序的灵活性和扩展性,在底层框架中用的比较多.业务层面的开发过程中尽量少用
缺点:
反射是一种解释操作,用于字段换个方法接入时要远慢与直接代码.
22.简述反射的使用场景?
实现RPC框架
实现ORM框架
拷贝属性值
23.简述实现ORM框架?
对象关系映射(Object Relational Mapping)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。简单说:ORM是通过使用描述对象和数据库之间映射的元数据.将程序中对象自动持久化到关系型数据库中。那么,如何实现持久化呢?一种简单的方案是采用硬编码方式.为每一种可能的数据库访问操作提供单独的方法
24.简述TCP中的三次握手?
第一次握手:
客户端发送sy包(syn=j)到服务器,并进入SYN_SEND状态.等待服务器的确认
第二次握手:
服务器收到Syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即syn+ack包.此时服务器进入SUN_RECV状态
第三次握手:
客户端收到服务器的syn+ack包,向服务器发送确认包(ack=k+1),此包发送完毕.客户端和服务器进入ESTABLEISHED状态,,完成三次握手
握手的过程中传送包里不含数据,三次握手完毕后,客户端与服务器才正式开始传递(发送)数据。理想状态下.TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前.TCP连接都将一直保持下去
断开连接时服务器和客户端均可以主动发起裂开TCO连接的请求.断开过程需要经过四次握手
第一次握手:
客户端发送报文告诉服务器没有数据要发送了
第二次握手:
服务端收到,再发送给客户端告诉它我收到了
第三次握手:
服务端想客户端发送报文,请求关闭连接
第四次握手:
客户端收到关闭连接的请求,想服务端发送报文,服务端关闭连接
25.简述TCP/IP五层模型?
应用层(Application)
传输层(Transport)
网络层(Network)
数据链路层(Data Link)
物理层(Physical)
26.简述TCP连接为什么是三次握手?两次可以吗?
为了实现高可靠数据传输,TCP协议的通信双方.都必须维护一个序列号.以标识发送出去 的数据包中.哪些是已经被双方收到的
三次握手的过程即使通信双方相互告知的序列号起始值,并确认对方已经收到了序列号 起始值的必经步骤
如果只是两次握手,至多只有连接发送方的起始序列号能够被确认.另一方选择的序列号 则得不到确认
27.为什么TCP是可靠的?UDP是不可靠的?为什么UDP比TCP快?
TCP/IP协议拥有三次握手双向机制,这一机制保证效验了数据.保证了它的可靠性.UDP就没有.udp在信息放送之后.不效验是否到达对方,所以不可靠
28.如果建立连接.客户端出现故障了怎么办?
TCP设有一个保活计时器.客户端如果出现故障.服务器不能一直的等待下去,白白浪费资源。服务器每收到一个客户端的请求后都会重新复位这个计时器.事假通常是设置为2 小时,若两个小时还没有收到客户端的任何数据.服务器就会发送一个探测报文段.以后每隔75秒发送一次。若一连发送了10个探测报文仍然没有回复(反应),服务器就认为客户端出了故障,接着就关闭连接
29.简述是什么是Http,Http与Https的区别?
Http是一个计算机时间里专门在两点之间传输文字、图片音频、视频等超文本数据的约 定和规范
区别:
协议:
http:运行在TCP之上.明文传输,客户端与服务器都无法验证对方的身份
https:身被SSL(Secure Scket Layer)外壳的HTTP,运行与SSL上,SSL运行与TCP纸 上.是添加了加密和认证机制的HTTP
端口:
HTTP:80
HTTPS:443
资源消耗:
HTTP:较少
HTTPS:由于加解密处理,会消耗很多的CPU和内存资源
开销:
HTTP:无需证书
HTTPS:需要证书,证书一般需要认证机构购买
加密机制:
HTTP:无
HTTPS:共享密钥加密和公开密钥加密并用的混合加密机制
安全性:
HTTP:比较弱
HTTPS:由于加密机制,安全性强
30.简述JVM内存模型?
线程独占:栈、本地方法栈
程序计数器线程共享:堆、方法区
31.你能保证GC执行吗?
不能,虽然我们能够调用System.gc()或者Runtime.gc() 但是,没有办法保证GC的执行
32.JVM类加载机制是什么?
JVM加载机制分为五个部分:
加载:是类加载过程中的一个阶段,这个阶段会在内存中生成一个代表这个类的 java.lang.class对象,作为方法区这个类的各种数据入口
验证:这个阶段主要的目的就是为了确保class文件的字节流中包含的信息是否符合 当前服你及的要求.并且不会危害虚拟机自身的安全
准备:准备阶段是正式为类变量分配内存并设置类变量的初始值阶段.即在方法区中 分配这些变量所使用的内存空间
解析:解析阶段是指虚拟机将常量池中的符号引用替换为直接引用的过程
初始化:类加载最后一个阶段,前面的累加载阶段之后,处理加载阶段可以自定义累 加器以外.其他操作都是由JVM主导,到了初始化阶段,才是整整执行类中定 义的java程序代码
33.堆和栈的区别是什么?
栈是运行时单位.代表着逻辑.内含基本数据类型和堆中对象引用.所在区域连续.没有碎片.堆是存储单位,代表着数据,可以被多个栈共享(包括成员中基本数据类型、引用和引用对象),所在的区域不连续.没有碎片
1.功能不同
栈内存用来存储局部变量和方法调用,而堆内存用来存储java中的对象。无论是成员变量、局部变量、还是类变量,他们指向的对象都存储在堆内存中
2.共享性不同
栈内存是线程私有的
堆内存是所有线程共有的
3.异常错误不同
如果栈内存或者堆内存不足都会抛异常
栈:java.lang.StackOverFlowError。堆:java.lang.OutOfMemoryError
4.空间大小
栈的内存空间大小远与堆的
34.什么是方法区?
又称为非堆区.用于存储已经被虚拟机加载的类信息、常量、静态变量,即时编译器优化后的代码等数据,在java1.7的永久代和1.8的元空间都是方法区的一种实现
35.简述java创建对象的过程?
JVM遇到一条新建对象的指令时首先检查这个指令的参数是否能在常量池中定义到一个类的符号引用。然后加载这个类,为对象分配内存。一种方法 指针碰撞 一种方法 空闲列表。本地线程缓冲分配(TLAB),将除对象头外的对象内存空间初始化为0,对对象头进行必要的设置
36.简述类的生命周期?
加载:查找并加载类的二进制数据,在java堆中也创建一个java.lang.Class类的对象
连接:连接有包含三块内容:验证、准备、初始化
验证:文件格式、元数据、字节码、符号引用验证
准备:为类的静态变量分配内存,并将其初始化为默认值
解析:把类中的符号引用转换为直接引用
初始化:为静态变量赋予正确的初始值
使用:new出对象程序中使用
卸载:执行垃圾回收
37.简述你知道的JVM性能调优?
调优包含多个层次,比如:架构调优、JVM调优、数据库调优、操作系统调优等
架构调优和代码调优都是JVM调优的基础,其中架构调优是对系统影响最大的
性能调优基本上按照以下步骤进行
明确优化目标
发现性能瓶颈
性能调优
通过监控及数据统计工具获得数据
明确是否达到目标
调优的背景:
Heap内存(老年代)继续上涨到设置的最大内存值
Full GC 次数频繁
GC 停顿时间过长(超过1秒)
应用出现OutOfMemory 等内存现象
应用中有使用本地缓存且占用大量的内存空间
系统吞吐量与相应性能不高或下降
调优步骤:
分析GC日志及dump文件,判断是否需要优化,确定瓶颈问题点
确定JVM调优量化目标
确定JVM调优参数(根据历史JVM参数来调整)
一次调优内存、延迟、吞吐量等指标
对比观察优化前后的差异
不断的分析和调整,直到找打合适的JVM参数配合
找到合适的参数,将这些参数应用到所有服务器,并进行后续跟踪