Javaの新しいVirtual Threadを試してみた

こんにちは、システムエンジニアのキュウです。去年、Java19のリリースに伴い、新機能のVirtual Threadがプレビュー状態になりました。いよいよ開発者が利用できるようになります。自分もこの機会に新しい「Thread」を試して、従来のJVM Threadとの違いを確認してみました。

Virtual Threadとは

Virtual Threadは、OpenJDKでのプロジェクトLoomの成果物です。Javaプラットフォームにも使いやすい軽量なThreadの実装を提供することを目標としています。

Virtual Threadと従来のJVM Threadとの違い

JVM Threadを使用する場合、次のコードが必要です。

Virtual Threadを使用する場合、次のコードとなります。

非常によく似ていますが、関数名が少し変更されたぐらいでしょうか?

実は、JVM ThreadとOS Threadの間には下記図のように1対1の関係があります。

JVM ThreadとOS Thread

JVM Threadの作成と破棄は、大量のシステムリソースを消費します。 多数のThreadでリクエストを処理するのは負荷の高い操作だと思われます。

Virtual Threadの方は下図のようにJVM ThreadとM対Nの関係に変わります。

JVM Threadよりも軽く実装されており、作成と破棄に消費するリソースがはるかに少なくなりそうです。その上、Virtual ThreadのスケジューリングはJavaプラットフォームによって制御されます。「Thread」は軽量になって使用するのに重くなりません。

Virtual Thread、JVM ThreadとOS Thread

高負荷の利用場面でも、Virtual Threadの導入により、Thread間の競合によって引き起こされるデッドロックや競合状態などの問題を回避でき、信頼性も向上するため、実際のパフォーマンスについてすごく楽しみです。

試してみる

Red Hatの記事では「Virtual ThreadのスケジューリングはJavaプラットフォームに渡される」とあるため、ここでSocket Serverを作って、Virtual ThreadとプーリングしたJVM Thread二つの方式で大量のリクエストを処理してみてパフォーマンスに大きな違いはあるか試してみます。

テストコード

まず、リクエストを処理するためのThreadプールを作成します。

JVM Threadを使用する場合:

Virtual Threadを使用する場合:

クライアントからのリクエストをハンドラに渡す。

ハンドラの中に受信したメッセージをEchoする。

試験結果

JMeter 試験結果

上図のように、2コアCPUの仮想サーバで同時リクエストが1000を超える場合のみ、Virtual ThreadはJVM Threadよりも優れた処理パフォーマンスを示しています。

最後に

自分の低スペックの仮想サーバではパフォーマンスに大きな差が見られなかったのは残念ですが、Virtual Threadの主戦場はハイスペックなサーバ上だと思われます。開発者の観点から見ると、Javaプラットフォームの進化に伴い、「Thread」を使用するコストはますます低くなり、頻繁の切り替えによるパフォーマンスの低下はまったく考慮しなくてもよくなります。将来「Thread」を自由に作成して使用できることを非常に期待しています。