Shoeisha Technology Media

CodeZine(コードジン)

特集ページ一覧

NetKernelでJavaの並行性を越える

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2009/02/09 14:00

 Javaはマルチスレッドと並行性の構造をサポートしていますが、最新のマルチCPUハードウェアに適合するアプリケーションの開発はそう簡単にはいきません。そのような場合、NetKernelなどの代替環境を用いると、ハードウェアの処理能力を余すことなく利用する道が開けます。

目次

Javaでの並行性プログラミング

 マルチコアおよびマルチCPUのシステムが普通に使われるようになった現在では、複数のタスクを同時に実行することが現実的な課題となっています。しかし、大抵のシステムでは、別のスレッドにタスクを実行させるというような簡単なやり方でこれに対応することはできません。使用するプログラミング言語から実行環境に問い合わせて、システムリソースの使用スケジュールを決定する必要があります。ハイレベルの並行性にかかわる関数を簡単に活用できるかどうかは、言語の構造に左右されます。

 従来は、「ヘルパー」を利用して複数のスレッドを行き来する方法がとられてきました。CPUは、あるスレッド上で行われているネットワークやI/O活動が完了するのを待つ間に、別のスレッドを実行して何らかの処理を行い、最初のスレッドの処理が完了して次に進める状態になったら再びそのスレッドに戻ることができます。この方法はアプリケーションの応答性を高めることには有効ですが、それでもコンピュータは一度に1つの作業しか行っていません。

 Java言語とJVMが登場する以前は、こうした並行プログラミングモデルを理解する人々は一部の上級開発者に限られていて、しかも処理能力を余すことなく利用するレベルには達していませんでした。並行性にかかわる構造が言語に直接組み込まれていなかったため、どうしてもどれか適当なスレッド処理ライブラリを選び、それに頼らざるを得なかったのです。これらのスレッド処理ライブラリをベースに作られたライブラリを使用すると、他の方式と適合しないことが度々ありました。POSIX標準化は一定の効果をもたらしましたが、その複雑さを解消することにはならず、ほとんどのソフトウェアエンジニアは手を出せませんでした。

 Javaは、この並行性の課題に取り組むために、比較的簡単でクロスプラットフォーム性の高い機構を言語およびJVMのレベルに導入しました。Javaがスレッド、すなわちRunnableインターフェースとモニタをサポートしたことは画期的でした。

 初期の一部のJVMは、まだ「グリーンスレッド」しか提供されていなかった時期に、ネイティブスレッドをサポートしました。これこそが、ネイティブスレッドの並行性に対応するJVMの舞台裏のマジックでした。これらの基本的なツールを用いることで、次のような移植性の高いマルチスレッドコードを簡単に記述できるようになりました。

Thread t1 = new Thread() {
    public void run() {
        System.out.println("Hello from Thread 1!");
    }
}

Thread t2 = new Thread() {
    public void run() {
        System.out.println("Hello from Thread 2!");
    }
}

t1.start();
t2.start();

 この方法の良い点は、簡単にコーディングできることでした。悪い点は、Threadインスタンスの乱用がオーバーヘッドを増やし、スケーラビリティを低下させることでした。大量のスレッドを作成すれば、アプリケーションは当然、スレッド間のコンテキストの切り替えのために立ち行かなくなります。開発者は、新規のThreadオブジェクトをできるだけ作成しないで、ある種のスレッドプールで実行するようにスケジュールされたRunnableインスタンスを使うよう推奨されました。標準のThreadPoolインスタンスと呼べるものが存在しない時期が数年続きましたが、その間に多くの効果的な方法が開発され、広く使われるようになりました。例えば次のようなものです。

Runnable r1 = new Runnable() {
    public void run() {
        System.out.println("It's good to be an r1 Runnable!");
    }
};

Runnable r2 = new Runnable() {
    public void run() {
        System.out.println("It's good to be an r2 Runnable!");
    }
}

// Create a ThreadPool with 3 threads waiting for something to do
ThreadPool tp = new ThreadPool(3); 
tp.execute(r1);
tp.execute(r2);

 このモデルはクライアントの要求をスレッドプールによって処理するという方式で、スケーラビリティの点で無理がなく、最終的に多くの組織でサーバーインフラストラクチャのベースとして使われるようになりました。スレッドのプールによってクライアントの要求を処理するという考え方です。ほとんどのサーブレットエンジンはこのような仕組みの下で動作していますが、シックSwingクライアントでも、長時間実行されるタスク(データベースの問い合わせや、別のスレッドへのRMI要求の発行など)をオフロードすることで応答性の向上が見られます(そうでなければSwingアプリケーションは応答性が低くて人気が出なかったことでしょう!)。


  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • japan.internet.com(ジャパンインターネットコム)

    japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.com や EarthWeb.c...

  • Brian Sletten(Brian Sletten)

    教養学部卒業のソフトウェアエンジニア。順方向学習技術に関心がある。システム設計者、開発者、助言者(メンター)、トレーナーとして活動している。世界中の会議で講演し、複数のオンラインメディアでWeb関連の技術に関して執筆を行っている。防衛、財務、商業など、経験は多岐にわたる。ネットワークマトリックススイ...

バックナンバー

連載:japan.internet.com翻訳記事

もっと読む

All contents copyright © 2005-2019 Shoeisha Co., Ltd. All rights reserved. ver.1.5