ハゲ頭だけが人を強くできる
以前ブログを書いていた時、よく書かれたブログが黙って集められていることに気づきました。最近抜け漏れのチェックをしていて、割と重要な知識点もあったのですが、以前のブログに書いていなかったので、空いた時間を利用して整理してみました(オススメ:JAVA面接問題集) )。
テキストの知識ポイント:
整数定数プール
TCPのアンパックとスティッキング
select,pol,epoll
単純な違いselect、poll、epoll
简单区别
jdk1.6以后对Synchronize锁优化
Java内存模型
本文力求简单讲清每个知识点,希望大家看完能有所收获
前阵子在群上看有人在讨论关于Integer的true或者false问题,我本以为我已经懂了这方面的知识点了。但还是做错了,后来去请教了一下朋友。朋友又给我发了另一张图:
后来发现这是出自《深入理解Java虚拟机——JVM高级特性与最佳实践(第2版)》中的10.3.2小节中~
public class Main_1 { public static void main(String[] args) { Integer a = 1; Integer b = 2; Integer c = 3; Integer d = 3; Integer e = 321; Integer f = 321; Long g = 3L; Long h = 2L; System.out.println(c == d); System.out.println(e == f); System.out.println(c == (a + b)); System.out.println(c.equals(a + b)); System.out.println(g == (a + b)); System.out.println(g.equals(a + b)); System.out.println(g.equals(a + h)); } }
你们可以先思考一下再往下翻看答案,看看能不能做对。
在解这道题之前,相信很多人都已经知道了,在Java中会有一个Integer缓存池,缓存的大小是:-128~127
答案是:
true
false
true
true
true
false
true
简单解释一下:
使用==
的情况:
如果比较Integer变量,默认比较的是地址值。
Java的Integer维护了从-128~127
的缓存池
如果比较的某一边有操作表达式(例如a+b),那么比较的是具体数值
使用equals()
的情况:
无论是Integer还是Long中的equals()
默认比较的是数值。
Long的equals()
方法,JDK的默认实现:会判断是否是Long类型
注意自动拆箱,自动装箱问题。
反编译一下看看:
import java.io.PrintStream; public class Main_1 { public static void main(String[] paramArrayOfString) { Integer localInteger1 = Integer.valueOf(1); Integer localInteger2 = Integer.valueOf(2); Integer localInteger3 = Integer.valueOf(3); Integer localInteger4 = Integer.valueOf(3); Integer localInteger5 = Integer.valueOf(321); Integer localInteger6 = Integer.valueOf(321); Long localLong = Long.valueOf(3L); // 缓存池 System.out.println(localInteger3 == localInteger4); // 超出缓存池范围 System.out.println(localInteger5 == localInteger6); // 存在a+b数值表达式,比较的是数值 System.out.println(localInteger3.intValue() == localInteger1.intValue() + localInteger2.intValue()); // equals比较的是数值 System.out.println(localInteger3.equals(Integer.valueOf(localInteger1.intValue() + localInteger2.intValue()))); // 存在a+b数值表达式,比较的是数值 System.out.println(localLong.longValue() == localInteger1.intValue() + localInteger2.intValue()); // Long的equals()先判断传递进来的是不是Long类型,而a+b自动装箱的是Integer类型 System.out.println(localLong.equals(Integer.valueOf(localInteger1.intValue() + localInteger2.intValue()))); // ... 最后一句在这里漏掉了,大家应该可以推断出来 } }
我使用的反编译工具是jd-gui
public void vectorTest(){ Vector<String> vector = new Vector<String>(); for(int i = 0 ; i < 10 ; i++){ vector.add(i + ""); } System.out.println(vector); }
-128~127
であることを多くの人がすでに知っていると思います。 img src="https://img.php.cn//upload/image/437/714/541/1533177807473997.png" title="1533177807473997.png" alt="Java 面接の質問集 - 内定をもらいやすくするために推奨される面接の質問"/>答えは:
簡単な説明:
を使用します==
ケース: 。 Java の Integer は -128~127
のキャッシュ プールを維持します
比較の片側に演算式がある場合 (a+b など)、比較は次のようになります。 特定の値
🎜🎜🎜🎜equals()
の使用: 🎜🎜equals()
のデフォルトは 🎜数値🎜 です。 🎜🎜🎜🎜JDK のデフォルト実装である Long の equals()
メソッド: 🎜それが Long 型であるかどうかを判断します🎜🎜🎜🎜🎜🎜自動アンボックス化と自動ボックス化の問題に注意してください。 🎜🎜🎜🎜 🎜🎜逆コンパイルして見てください: 🎜rrreee🎜 私が使用する逆コンパイル ツールは jd-gui
です。まだ逆コンパイルを試したことがない場合は、ダウンロードして試してみてください: 🎜🎜🎜 🎜https://github.com/java-decompiler/jd-gui/releases 🎜🎜🎜🎜 2. 同期ロックの最適化メソッドとは何ですか🎜🎜 マルチスレッドの記事レビュー: 🎜🎜🎜🎜ThreadLocal はとてもシンプルです 🎜🎜🎜 🎜3分でマルチスレッド ドアに入ることができます! 🎜🎜🎜🎜スレッドソースコード解析🎜🎜🎜🎜マルチスレッドの基礎知識ポイント!マルチスレッドを学習し、半分の労力で 2 倍の結果を得る方法について読んでください🎜🎜🎜🎜Java ロック メカニズムについて学び🎜🎜🎜🎜AQS を簡単に見てみましょう🎜🎜🎜🎜それについて学ぶにはサブクラスをロックしてください🎜🎜🎜🎜スレッド プール、それについて本当に知りたくないですか? 🎜🎜🎜🎜マルチスレッドのデッドロックはとても単純です🎜🎜🎜🎜Javaマルチスレッドを支援する3人の若者🎜🎜🎜🎜以前マルチスレッドの記事を書いたときに、同期ロックは次の後に発生すると簡単に言いましたjdk1.6 スピン ロックへの適応、ロックの削除、ロックの粗密化、軽量ロック、バイアスされたロックなど、さまざまな最適化があります。 🎜🎜🎜🎜🎜これらの最適化は非常に理解するのが難しいと思っていましたが、実は~~~簡単に理解するだけで簡単に理解できます。 🎜🎜2.1 スピンロックに適応する🎜🎜ロック競合はカーネルモードで行われ、ユーザーモードからカーネルモードへの🎜切り替え🎜が行われますが、これには非常に時間がかかります。 🎜🎜🎜スピンロック🎜が表示される理由は、ほとんどの場合、🎜ロックの占有はカーネルモードに切り替えるのにかかる時間よりも短い時間しか続かない🎜ため、その前にスレッドを待機させてください。カーネル モードに入る 限られた時間内にロックを取得できれば、多くの無駄な時間が回避されます。そうでない場合は、カーネル モードに移行してロックを獲得します。 🎜🎜JDK 1.6 で適応型スピン ロックが導入されました。これは、🎜スピンの時間が固定されず、スピンするかどうかに関係なく、よりスマートになる🎜ことを意味します。 🎜自旋锁在JDK1.4.2中就已经引入,只不过默认是关闭的,可以使用-XX:+UseSpinning
参数来开启,在JDK1.6中就已经改为默认开启了。
如果JVM明显检测到某段代码是线程安全的(言外之意:无锁也是安全的),JVM会安全地原有的锁消除掉!
比如说:
public void vectorTest(){ Vector<String> vector = new Vector<String>(); for(int i = 0 ; i < 10 ; i++){ vector.add(i + ""); } System.out.println(vector); }
Vector是默认加锁的,但JVM如果发现vector变量仅仅在vectorTest()
方法中使用,那该vector是线程安全的。JVM会把vector内部加的锁去除,这个优化就叫做:锁消除。
默认情况下,总是推荐将同步块的作用范围限制得尽量小。
但是如果一系列的连续操作都对同一个对象反复加锁和解锁,甚至加锁操作是出现在循环体中的,频繁地进行互斥同步操作也会导致不必要的性能损耗。
JVM会将加锁的范围扩展(粗化),这就叫做锁粗化。
轻量级锁能提升程序同步性能的依据是“对于绝大部分的锁,在整个同步周期内都是不存在竞争的”,这是一个经验数据。
如果没有竞争,轻量级锁使用CAS操作避免了使用互斥量的开销
但如果存在锁竞争,除了互斥量的开销外,还额外发生了CAS操作,因此在有竞争的情况下,轻量级锁会比传统的重量级锁更慢。
简单来说:如果发现同步周期内都是不存在竞争,JVM会使用CAS操作来替代操作系统互斥量。这个优化就被叫做轻量级锁。
偏向锁就是在无竞争的情况下把整个同步都消除掉,连CAS操作都不做了!
偏向锁可以提高带有同步但无竞争的程序性能。它同样是一个带有效益权衡(Trade Off)性质的优化,也就是说,它并不一定总是对程序运行有利,如果程序中大多数的锁总是被多个不同的线程访问,那偏向模式就是多余的。在具体问题具体分析的前提下,有时候使用参数-XX:-UseBiasedLocking
来禁止偏向锁优化反而可以提升性能。
自适应偏向锁:自旋时间不固定
锁消除:如果发现代码是线程安全的,将锁去掉
锁粗化:加锁范围过小(重复加锁),将加锁的范围扩展
轻量级锁:在无竞争的情况下使用CAS操作去消除同步使用的互斥量
偏向锁:在无竞争环境下,把整个同步都消除,CAS也不做。
参考资料:
https://blog.csdn.net/chenssy/article/details/54883355
这是在看wangjingxin大佬面经的时候看到的面试题,之前对TCP粘包,拆包没什么概念,于是就简单去了解一下。
在进行Java NIO学习时,可能会发现:如果客户端连续不断的向服务端发送数据包时,服务端接收的数据会出现两个数据包粘在一起的情况。
TCP的首部格式:
TCP是基于字节流的,虽然应用层和TCP传输层之间的数据交互是大小不等的数据块,但是TCP把这些数据块仅仅看成一连串无结构的字节流,没有边界;
从TCP的帧结构也可以看出,在TCP的首部没有表示数据长度的字段
基于上面两点,在使用TCP传输数据时,才有粘包或者拆包现象发生的可能。
一个数据包中包含了发送端发送的两个数据包的信息,这种现象即为粘包
接收端收到了两个数据包,但是这两个数据包要么是不完整的,要么就是多出来一块,这种情况即发生了拆包和粘包
拆包和粘包的问题导致接收端在处理的时候会非常困难(因为无法区分一个完整的数据包)
サブパッケージ化メカニズムには一般に 2 つの 共通 ソリューションがあります:
1、特殊文字制御
2、ヘッダーの大文字にデータ パケットの長さを追加する
netty を使用する場合は、解凍と貼り付けの問題を解決するための特別なエンコーダーとデコーダーがあります。
ヒント:UDP にはパケット固着問題はありませんが、パケット損失やパケット障害が発生します。不完全なパッケージは存在せず、受け取ったパッケージはすべて完全に正しいものになります。送信されるデータ ユニット プロトコルは UDP メッセージまたはユーザー データグラムであり、送信時に結合も分割もされません。
NIO レビュー:
JDK10 がリリースされました。nio についてどれくらい知っていますか?
これは Linux で I/O 再利用モデルを実装する方法です:
select/poll/epoll
関数の 1 つを呼び出し、複数のファイル記述子がある場合は Return if を渡します。ファイル記述子の準備ができている場合は、タイムアウトになるまでブロックされます。 select/poll/epoll
其中一个函数,传入多个文件描述符,如果有一个文件描述符就绪,则返回,否则阻塞直到超时。
这几个函数是有些区别的,可能有的面试官会问到这三个函数究竟有什么区别:
区别如下图:
两句话总结:
select和poll
都需要轮询每个文件描述符,epoll
基于事件驱动,不用轮询
select和poll
每次都需要拷贝文件描述符,epoll
不用
select
最大连接数受限,epoll和poll
最大连接数不受限
tips:epoll在内核中的实现,用红黑树管理事件块
现在3y在公司里边实习,写完的代码需要给测试测一遍。
select/poll
情况:
开发在写代码,此时测试挨个问所有开发者,你写好程序了没有?要测试吗?
epoll
選択してポーリング
epoll
はイベント駆動型であり、ポーリングは必要ありません
select and poll
は毎回ファイル記述子をコピーする必要があります。 epoll
は使用されません
select
接続の最大数は制限されています。epoll と Paul
接続の最大数は制限されていません現在、3 歳は会社でインターン中であり、書かれたコードをテストする必要があります。
select/poll
状況:
開発者はコードを書いています。この時点で、テストはすべての開発者に 1 つずつ尋ねます
、プログラムの作成は完了しましたか?テストしたいですか?epoll
状況:
その他の一般的な説明 [1]:
その他の一般的な説明 [2]: 簡単な例を挙げると (あまり鮮明ではないかもしれませんが)、レストランのウェイター (カーネル) を選択/ポーリングすると、ホテルのオーナー (ユーザー プログラム) に次のように伝えます。このウェイターを知っている人は、ゲストがどのテーブルの料金を払っているのかをボスに伝えてください。上司は各テーブルに行って「支払いますか?」と尋ねなければなりません。 epoll ホテルのウェイター (カーネル) はホテルのオーナー (ユーザー プログラム) に次のように指示します。「ゲスト 1、2、5 はチェックアウトします。ボスはテーブル 1、2、5 に直接行ってお金を受け取ることができます5」。 Java メモリ モデル
JVM はどのようにして始めてから諦めるまでに至ったのですか?
~~~ 幸いなことに、何人かの熱心なネチズンがそれを私に指摘してくれました。 JVM メモリ構造:
read (読み取り): メインメモリ変数に作用し、変数値をメインメモリからスレッドの作業メモリに転送し、後続のロードアクションで使用できるようにします
load (ロード) : 作業メモリ変数に作用し、読み取り操作によってメイン メモリから取得した変数値を作業メモリ内の変数のコピーに置きます。
use (使用): 作業メモリ内の変数に作用し、作業メモリ内の変数値を実行エンジンに渡します。これは、仮想マシンがその値を使用する必要があるバイトコード命令に遭遇するたびに実行されます。変数を操作します。
assign (割り当て): 作業メモリ内の変数に作用し、実行エンジンから受け取った値を作業メモリ内の変数に割り当てます。これは、仮想マシンが値を割り当てるバイトコード命令に遭遇するたびに実行されます。変数に操作します。
store (ストレージ): 作業メモリ内の変数に作用し、後続の書き込み操作のために作業メモリ内の変数の値をメインメモリに転送します。
write (書き込み): メインメモリ内の変数に作用し、作業メモリ内の変数の値からメインメモリ内の変数にストア操作を転送します。
Java メモリ モデルは、同時プロセスでの原子性、可視性、順序付けの処理方法を中心に構築されています
これら 3 つの特性原子性を保証する操作:read、load、assign、use、store和write
同期ロック
として上で述べたように、順序性は揮発性ロックと同期ロックによって保証できますが、プログラムを作成するときにコードの順序性を常に意識するわけではありません。実際、Java には、happens-before 原則(happens-before)
を介して同時環境で 2 つの問題を解決するために使用できます。ルール すべての問題 オペレーション間で競合が発生する可能性があるかどうか
。操作 A が操作 B より前に確実に実行されることを確認できます (並べ替えの問題は発生しません)
以上がJava 面接の質問集 - 内定をもらいやすくするために推奨される面接の質問の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。