2

ここでスケジューラはどのように機能しますか? バックグラウンドで新しいスレッドを作成し、コールバックのようにメイン スレッドで Run メソッドを実行しますか。? . run メソッドが実行されるとき、それはメインスレッドに属していますか?

 classA implements Runnable
 {
     
    public void Run()
    {
       System.out.println(Thread.currentTread().getName());
    }
    
    public static void main(String args[])
    {
      Thread.currentThread().setName("Main");
    
      ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
      scheduler.scheduleAtFixedRate(this, 250, 250, TimeUnit.MILLISECONDS);
    
    } 
}

ありがとう。

4

1 に答える 1

4

SingleThreadScheduledExecutor はどのように機能しますか?

最大で 1 つのスレッドを含むスレッド プールを作成します。これにより、(このエグゼキューターでスケジュールされている) 一度に 1 つのタスクのみが実行されることが保証されます。
タスクは、タスクを送信したスレッドではなく、エグゼキュータの単一スレッドで実行されます。

メソッドが「メインスレッド」で実行されるようにすることはできますか?*

何でも「作る」ことができますよね?ただし、ExecutorService ではなく、独自のスレッドで動作するように設計されています。

ではどうですか?

基本的に、すべてを提供する環境にいるか (Swing の UI アプリケーションなど)、これが該当するかどうかを確認してください (Swing には Event Dispatch Thread があります)。あなたはいくつかの仕事を必要とします。したがって、この作業に進む前に、メインスレッドで作業する必要があることを最初に確認することをお勧めします。

この作業には何が含まれますか?

特別な作業をしなくても、メイン スレッドは中断不可能なステートメント フローであるコードを実行します。それらは一度書かれたものであり、だれもあなたのメインスレッドにコードを「注入」することはできません (まあ、あなたが本当にメモリをめちゃくちゃにしない限り、それはできますが、それは通常行うことではありません)。

そのため、メイン スレッドは、タスク A、B、C、D の順に、できるだけ速く (または許可されている) タスクを実行するのに忙しいです。このフローの途中で「タスク E」を投入することはできません。

比喩的に言えば、これはコード内でランダムな行を選択し、そこに別のメソッドのステートメントを追加することと同じです: 保証されたクラッシュ (コンテキストとは何か、スタックとは何か、この特定の行に存在する変数は何か、どの値を持つのか) : 予測不能)。これは起こり得ません。

したがって、タスク A が「4 秒で実行するタスクを作成する」であっても、次のようになります。別のスレッドで 4 秒後にタイマーの期限切れが通知され、この別のスレッドが何をすべきかを決定します。メインスレッドは「タスク B」を実行している最中であり、他にできることは何もないためです。

では、基本的には・・・できないのでしょうか?

ええ、できます。しかし、それが機能するためには、「タスク A」(または B、または C)を特別なものにする必要があります。外部からのイベントを定期的に「待機」するようにメイン スレッドを設計する必要があります。
そして、それを行う方法はそれほど多くありません。定期的に何かを行います。メインスレッドに「ループ」を実行させる必要があります。このパターンは実行ループと呼ばれます。多くの UI フレームワークがこの方法で実行されます。

何が起こるかというと:

  1. キューを作成し、プログラムからグローバルにアクセスできるようにします (たとえば、Singleton パターン)。このキューの目的は、メイン スレッドが実行することになっているすべてのワーク ユニットを受け取ることです。
  2. 開始時に、メイン スレッドがセカンダリ スレッドを生成するようにします。このセカンダリ スレッドは、ステップ 3 の後にアプリケーションの初期化プロセスと寿命を継続する責任があります。
  3. キューからの新しいイベントを待機する無限ループにメインスレッドを入力させます

「セカンダリ」スレッドを使用すると、最初のタイマーの設定など、好きなことを行うことができます。タイマーが起動すると、実行する作業 (Runnable インスタンスなど) をキューに送信する必要があります。メインスレッドは、実行可能なインラインの実行を取得します。

それは効率的ですか?イベントを待っていますか?

はい、できます。並行性のために設計された目的のオブジェクト ( ConcurrentQueue?) を使用すると、実際には作業を実行せず、待機中にリソースを浪費します。内部で起こっていることは、新しいユニットが利用可能であることをオペレーティング システムがスレッドに「通知」することです。つまり、「何かすることはありますか? はいの場合は実行し、いいえの場合は 3 秒待ちます」という無限ループではありません。それは、「用事があれば知らせて」です。

これを実際に実装するためのJAR / libまたはツールまたはベストプラクティスを知りません。ほとんどの場合、環境がこれを提供するか (Swing のìnvokeLater)、または私はこの種のものを必要としませんでした。理論的にはわかるのですが、実際に実装するのは意外と難しいのではないでしょうか。

このパターンのウィキペディアのエントリ: http://en.wikipedia.org/wiki/Event_loop
ゲーム プログラミングでは、同等のパターンである「ゲーム ループ」がよくあります。

于 2014-08-01T09:08:32.677 に答える