起源不详了
原文地址: Java 根底面试题 -20211228
欢送拜访我的博客: http://blog.duhbb.com/
题目
- 转发和重定向的区别
- HashMap 和 HashTable 的区别
- 什么是死锁, 产生死锁的必要条件是什么? 如何防止死锁的产生?
- 深拷贝和浅拷贝的区别
- Java 中正文的代码肯定不会执行吗? 没有正文的代码肯定会执行吗?
转发和重定向的区别
- 申请转发: 客户浏览器发送 http 申请,web 服务器承受此申请, 调用外部的一个办法在容器外部实现申请解决和转发动作, 将指标资源发送给客户; 在这里, 转发的门路必须是同一个 web 容器下的 url, 其不能转向到其余的 web 门路下来, 两头传递的是本人的容器内的 request. 在客户浏览器门路栏显示的依然是其第一次拜访的门路, 也就是说客户是感觉不到服务器做了转发的. 转发行为是浏览器只做了一次拜访申请.
- 重定向过程: 客户浏览器发送 http 申请,web 服务器承受后发送 302 状态码响应及对应新的 location 给客户浏览器, 客户浏览器发现是 302 响应, 则主动再发送一个新的 http 申请, 申请 url 是新的 location 地址, 服务器依据此申请寻找资源并发送给客户. 在这里 location 能够重定向到任意 URL, 既然是浏览器从新收回了申请, 则就没有什么 request 传递的概念了. 在客户浏览器门路栏显示的是其重定向的门路, 客户能够察看到地址的变动的. 重定向行为是浏览器做了至多两次的拜访申请的.
上面通过一张图来比照两者的区别:
区别 | 重定向 | 申请转发 |
---|---|---|
在哪里实现 | 客户端实现 (能够在不同的服务器下实现) | 服务器端实现 (必须是在同一台服务器下实现) |
浏览器发送申请的次数 | 2 次或者 2 次以上 | 1 次 |
地址栏 URL 是否产生扭转 | 地址栏发生变化 | 地址栏的地址不变 |
是否共享 request | 不共享数据 (通过重定向后,request 内的对象将无奈应用) | 共享数据 (以前的 request 中寄存的变量不会生效, 就像把两个页面拼到了一起) |
第二次申请发起者 | 浏览器 | 服务器 |
第二次的申请门路形式 | 绝对路径 | 相对路径 |
速度 | 因为还要浏览器发送第二次申请, 重定向绝对慢一点 | 快 |
语句 | response.sendRedirect(“success.jsp”); | request.getRequestDispatcher(“success.jsp”).forward(request,response); |
原文链接:https://blog.csdn.net/Weixiao…
HashMap 和 HashTable 的区别
- HashMap 不是线程平安的
HashMap 是 map 接口的实现类, 是将键映射到值的对象, 其中键和值都是对象, 并且不能蕴含反复键, 但能够蕴含反复值.HashMap 容许 null key 和 null value, 而 HashTable 不容许. - HashTable 是线程平安 Collection.
HashMap 是 HashTable 的轻量级实现, 他们都实现了 Map 接口, 次要区别在于 HashMap 容许 null key 和 null value, 因为非线程平安, 效率上可能高于 Hashtable.
区别如下:
- HashMap 容许将 null 作为一个 entry 的 key 或者 value, 而 Hashtable 不容许.
- HashMap 把 Hashtable 的 contains 办法去掉了, 改成 containsValue 和 containsKey. 因为 contains 办法容易让人引起误会.
- HashTable 继承自 Dictionary 类, 而 HashMap 是 Java1.2 引进的 Map interface 的一个实现.
- HashTable 的办法是 Synchronize 的, 而 HashMap 不是, 在多个线程拜访 Hashtable 时, 不须要本人为它的办法实现同步, 而 HashMap 就必须为之提供外同步.
- Hashtable 和 HashMap 采纳的 hash/rehash 算法都大略一样, 所以性能不会有很大的差别.
作者:hunter886
链接:https://www.jianshu.com/p/5c3…
起源: 简书
著作权归作者所有. 商业转载请分割作者取得受权, 非商业转载请注明出处.
那为什么 HashTable 的 key 或者 value 不能为 null 呢?
以下答复摘自 stackoverflow:
Hashtable 是较古老的类, 通常不激励应用它.
在之后的应用中, 设计人员发现开发中通常须要一个空键或者空值, 于是就在 HashMap 中减少了对 null 的反对.
HashMap 最为 HashTable 之后实现的类, 具备更高级的性能, 这基本上只是对 Hashtable 性能的改良.
创立 HashMap 时, 它专门设计为将空值作为键解决并将其作为非凡状况解决.
补充:JDK 源码中作者的正文:
To successfully store and retrieve objects from a Hashtable, the objects used as keys must implement the hashCode method and the equals method.
要从 Hashtable 胜利存储和检索对象, 用作键的对象必须实现 hashCode 办法和 equals 办法.
因为 null 不是对象, 因而不能在其上调用 equals() 或 hashCode(), 因而 Hashtable 无奈将其计算哈希值以用作键.
作者: 王李红
链接:https://www.zhihu.com/questio…
起源: 知乎
著作权归作者所有. 商业转载请分割作者取得受权, 非商业转载请注明出处.
死锁
什么是死锁?
所谓死锁, 是指多个过程在运行过程中因抢夺资源而造成的一种僵局, 当过程处于这种僵持状态时, 若无外力作用, 它们都将无奈再向前推动. 因而咱们举个例子来形容, 如果此时有一个线程 A, 依照先锁 a 再取得锁 b 的的程序取得锁, 而在此同时又有另外一个线程 B, 依照先锁 b 再锁 a 的程序取得锁.
产生死锁的起因?
可归结为如下两点:
竞争资源
零碎中的资源能够分为两类:
- 可剥夺资源, 是指某过程在取得这类资源后, 该资源能够再被其余过程或零碎剥夺,CPU 和主存均属于可剥夺性资源;
- 另一类资源是不可剥夺资源, 当零碎把这类资源分配给某过程后, 再不能强行发出, 只能在过程用完后自行开释, 如磁带机, 打印机等.
产生死锁中的竞争资源之一指的是竞争不可剥夺资源 (例如: 零碎中只有一台打印机, 可供过程 P1 应用, 假设 P1 已占用了打印机, 若 P2 持续要求打印机打印将阻塞)
产生死锁中的竞争资源另外一种资源指的是竞争长期资源 (长期资源包含硬件中断, 信号, 音讯, 缓冲区内的音讯等), 通常音讯通信程序进行不当, 则会产生死锁
过程间推动程序非法
若 P1 放弃了资源 R1,P2 放弃了资源 R2, 零碎处于不平安状态, 因为这两个过程再向前推动, 便可能产生死锁.
例如, 当 P1 运行到 P1:Request(R2) 时, 将因 R2 已被 P2 占用而阻塞; 当 P2 运行到 P2:Request(R1) 时, 也将因 R1 已被 P1 占用而阻塞, 于是产生过程死锁
死锁产生的 4 个必要条件?
产生死锁的必要条件:
- 互斥条件: 过程要求对所调配的资源进行排它性管制, 即在一段时间内某资源仅为一过程所占用.
- 申请和放弃条件: 当过程因申请资源而阻塞时, 对已取得的资源放弃不放.
- 不剥夺条件: 过程已取得的资源在未应用完之前, 不能剥夺, 只能在应用完时由本人开释.
- 环路期待条件: 在产生死锁时, 必然存在一个过程 – 资源的环形链.
解决死锁的根本办法
预防死锁:
- 资源一次性调配: 一次性调配所有资源, 这样就不会再有申请了:(毁坏申请条件)
- 只有有一个资源得不到调配, 也不给这个过程调配其余的资源:(毁坏请放弃条件)
- 可剥夺资源: 即当某过程取得了局部资源, 但得不到其它资源, 则开释已占有的资源 (毁坏不可剥夺条件)
- 资源有序调配法: 零碎给每类资源赋予一个编号, 每一个过程按编号递增的程序申请资源, 开释则相同 (毁坏环路期待条件)
1 以确定的程序取得锁
如果必须获取多个锁, 那么在设计的时候须要充分考虑不同线程之前取得锁的程序.
针对两个特定的锁, 开发者能够尝试依照锁对象的 hashCode 值大小的程序, 别离取得两个锁, 这样锁总是会以特定的程序取得锁, 那么死锁也不会产生. 问题变得更加简单一些, 如果此时有多个线程, 都在竞争不同的锁, 简略依照锁对象的 hashCode 进行排序 (单纯依照 hashCode 程序排序会呈现 ” 环路期待 ”), 可能就无奈满足要求了, 这个时候开发者能够应用银行家算法, 所有的锁都依照特定的程序获取, 同样能够避免死锁的产生, 该算法在这里就不再赘述了, 有趣味的能够自行理解一下.
2 超时放弃
当应用 synchronized 关键词提供的内置锁时, 只有线程没有取得锁, 那么就会永远期待上来, 然而 Lock 接口提供了 boolean tryLock(long time, TimeUnit unit) throws InterruptedException 办法, 该办法能够依照固定时长期待锁, 因而线程能够在获取锁超时当前, 被动开释之前曾经取得的所有的锁. 通过这种形式, 也能够很无效地防止死锁.
防止死锁
预防死锁的几种策略, 会重大地侵害零碎性能. 因而在防止死锁时, 要施加较弱的限度, 从而取得 较称心的零碎性能. 因为在防止死锁的策略中, 容许过程动静地申请资源. 因此, 零碎在进行资源分配之前事后计算资源分配的安全性. 若此次调配不会导致系统进入不平安的状态, 则将资源分配给过程; 否则, 过程期待. 其中最具备代表性的防止死锁算法是银行家算法.
银行家算法: 首先须要定义状态和平安状态的概念. 零碎的状态是以后给过程调配的资源状况. 因而, 状态蕴含两个向量 Resource(零碎中每种资源的总量) 和 Available(未调配给过程的每种资源的总量) 及两个矩阵 Claim(示意过程对资源的需要) 和 Allocation(示意以后调配给过程的资源). 平安状态是指至多有一个资源分配序列不会导致死锁. 当过程申请一组资源时, 假如批准该申请, 从而扭转了零碎的状态, 而后确定其后果是否还处于平安状态. 如果是, 批准这个申请; 如果不是, 阻塞该过程晓得批准该申请后零碎状态依然是平安的.
检测死锁
- 首先为每个过程和每个资源指定一个惟一的号码;
- 而后建设资源分配表和过程期待表.
死锁检测的工具
- Jstack 命令
jstack 是 java 虚拟机自带的一种堆栈跟踪工具.jstack 用于打印出给定的 java 过程 ID 或 core file 或近程调试服务的 Java 堆栈信息. Jstack 工具能够用于生成 java 虚拟机以后时刻的线程快照. 线程快照是以后 java 虚拟机内每一条线程正在执行的办法堆栈的汇合, 生成线程快照的次要目标是定位线程呈现长时间进展的起因, 如线程间死锁, 死循环, 申请内部资源导致的长时间期待等. 线程呈现进展的时候通过 jstack 来查看各个线程的调用堆栈, 就能够晓得没有响应的线程到底在后盾做什么事件, 或者期待什么资源. - JConsole 工具
Jconsole 是 JDK 自带的监控工具, 在 JDK/bin 目录下能够找到. 它用于连贯正在运行的本地或者近程的 JVM, 对运行在 Java 应用程序的资源耗费和性能进行监控, 并画出大量的图表, 提供弱小的可视化界面. 而且自身占用的服务器内存很小, 甚至能够说简直不耗费.
解除死锁:
当发现有过程死锁后, 便应立即把它从死锁状态中解脱进去, 常采纳的办法有:
- 剥夺资源: 从其它过程剥夺足够数量的资源给死锁过程, 以解除死锁状态;
- 吊销过程: 能够间接吊销死锁过程或吊销代价最小的过程, 直至有足够的资源可用, 死锁状态. 打消为止; 所谓代价是指优先级, 运行代价, 过程的重要性和价值等.
原文链接: https://www.cnblogs.com/crazy…
深拷贝和浅拷贝的区别
所谓深浅拷贝, 都是进行复制, 那么区别次要在于复制进去的新对象和原来的对象是否会相互影响, 改一个, 另一个也会变.
- 浅拷贝: 对于仅仅是复制了援用 (地址), 换句话说, 复制了之后, 原来的变量和新的变量指向同一个货色, 彼此之间的操作会相互影响, 为 浅拷贝.
- 深拷贝: 而如果是在堆中从新分配内存, 领有不同的地址, 然而值是一样的, 复制后的对象与原来的对象是齐全隔离, 互不影响, 为深拷贝.
深浅拷贝的次要区别就是: 复制的是援用 (地址) 还是复制的是实例.
https://github.com/YvetteLau/…
Java 正文
感觉这个问题有点弱智:
- 正文了的代码坑定不会执行啊, 要是能执行那才是奇了怪了;
- 没有正文的代码不肯定会执行的
if (1 == 2) {System.out.println("never get here!");
}
你说这个会执行吗?
原文地址: Java 根底面试题 -20211228
欢送拜访我的博客: http://blog.duhbb.com/