[JAVA]2つのマルチスレッド


スレッドのステータス


スレッドには複数のステータスがあります.
待機状態:未スケジュール、運転待ち
実行:スケジューリングスレッドとして選択された非スレッドがCPUを占有しrun()メソッドを実行
一時停止:スレッドが実行できません
  • WAITING:他のスレッドの通知を待つステータス
  • TIMED WAITING:所定時間待機状態
  • BLOCKED:使用待ちオブジェクトロック解除ステータス
  • 終了:スレッドの実行が終了しました

    スレッドの状態はThreadクラスのgetState()メソッドとしてインポートできます.
    Thread.State state = thread.getState();

    スレッドステータスの制御


    マルチスレッドプログラムを記述するためには,微細なスレッド状態制御が必要であり,状態制御が正しくないとプログラムが不安定になり,ハングアップすることもある.
    これがマルチスレッドプログラミングが困難な理由です.

    じょうたいせいぎょほうしき


    sleep( )
    Thread.sleep()メソッドを呼び出すスレッドは、所定の時間内に一時停止状態にあり、実行状態に戻ります.
    yield( )
    Thread.降伏()メソッドを呼び出すスレッドは、実行状態を別のスレッドに移行し、それ自体が実行待ち状態になります.
    実行状態を優先度の高い方法に移行することで、プログラム全体のパフォーマンスを向上させることができます.
    join( )
    スレッドは独立して実行されますが、他のスレッドの操作結果を待つ必要がある場合があります.
    Thread.join()メソッドが呼び出されると、スレッドは他のスレッドのタスクの終了を待つ.
    Thread A
    threadB.start();
    threadB.join();
    // Thread B의 작업 종료를 기다림
    Thread B
    run(){
       ...
    }
    wait()、notify()およびnotifyAll()-スレッド間コラボレーション
    スレッド間で正しく交互に作業する必要がある場合に使用します.
    Thread.wait()メソッドを呼び出すと、スレッドは一時停止状態になります.
    Thread.notify()メソッドを呼び出すと、一時停止中のスレッドが実行待ち状態になります.
    Thread.notifyAll()メソッドを呼び出すと、一時停止中のすべてのスレッドが実行待ち状態になります.<!>「正しい」というキーワードは、想像以上に正確で簡潔に処理することが求められると思います.
    場合によっては異なりますが、スレッド間干渉を正確に制御できる場合には良いと思います.
    stop( )
    Threadを直ちに終了するためにstop()メソッドが提供されていたが、Depentedされた.
    どうしてこんなことになったの?
    Threadがすぐに終了すると、Threadが使用するリソースが不安定になる可能性があります.
    では、Threadを安全に閉じる方法を見てみましょう.
    ストップフラグ
    スレッドはrun()メソッドの終了時に正常に終了するので、このrun()メソッドを正常に終了させることが望ましい.
    public class YourThread extends Thread {
    	private boolean stop; // stop flag
    	
    	public void run() {
    		while(!stop) {
    			// 스레드의 작업
    		}
    		// 스레드가 사용한 자원 정리
    	}
    }
    △ええと、もっといい方法はありませんか.
    わりこみほうしき
    スレッドが「一時停止状態」の場合、割り込み()メソッドによって割り込みException異常が発生します.
    例外処理を使用すると、スレッドのrun()メソッドを正常に終了させることができます.
    public void run() {
    	try {
    		while(true) {
    			// 스레드 작업
    			Thread.sleep(1); // 일시 정지
    		}
    	} catch (InterruptedException e) {}
    	
    	// 스레드가 사용한 자원 정리
    }
    このコードで注目すべき点は、Threadが一時停止状態である必要があることです.
    Threadは例外が発生するには一時停止状態でなければならないので、スレッドを終了することができます.
    したがって,ほんの少しでもsleep()メソッドを呼び出す.
    ?? バカだろ?
    仕事をするたびに少し止まります.

    だからもっとスマートな方法があります!
    割り込み()メソッドを呼び出すかどうか
    interrupt()が呼び出されると、interrupted()メソッドはtrueを返します.
    interrupted()は静的メソッドであり、isInterrupted()はインスタンスメソッドである.
    2つの方法を使用すると、スレッドは、割り込み()を呼び出すかどうかをアクティブに決定し、安全に終了することができます.
    (どちらでも良い)
    public class YourThread extends Thread {
    	public void run() {
    		while(true){
    			// 스레드 작업
    			if(Thread.interrupted()) {
    				break;
    			}
    		}
    		// 스레드가 사용한 자원 정리
    	}
    }

    デーモンプロセススレッド


    デーモン・スレッドは、プライマリ・スレッドの作業を支援する補助タスクを実行するスレッドです.
    メインスレッドの補助スレッドと見なすことができます.
    したがって、マスタースレッドが終了すると、デーモンスレッドは自動的に終了します.
    それ以外に、デーモンスレッドは通常のスレッドとあまり違いません.
    デモンズ・レイドはどこだ?
    デーモンスレッドを適用する例としては、ワードプロセッサの自動記憶、メディアプレーヤーのビデオ再生、音楽再生、ゴミ収集器などがあります.これらの機能は、もちろん、メインスレッド-ワード処理、メディアプレーヤー、JVM終了時に一緒に終了します.
    スレッドをデーモンにするには、デーモンになるスレッドのsetDaemon(true)を呼び出すことができます.
    次のコードのメインスレッドはメインスレッドで、AutoSaveThreadはデーモンスレッドです.
    public static void main(String[] args) {
    	AutoSaveThread thread = new AutoSaveThread();
    	thread.setDaemon(true);
    	thread.start();
    	...
    }

    スレッドグループ


    スレッドグループは、関連するスレッドをグループ化して管理するために使用されます.
    JVM実行後、システムスレッドグループを作成します.
    JVMを実行するために必要なスレッドを作成し、システムスレッドグループに含めます.
    次にmainをシステムのサブスレッドグループとして作成し、メインスレッドをmainスレッドグループに含めます.
    大まかな構造
    system thread group
  • main thread group
  • main thread
  • ...
  • another thread group
  • ねじは、ねじグループに含める必要があります.ねじグループに明示的に含まれていない場合は、基本的には作成されたねじグループに属します.
    我々が生成したワークスレッドの大部分はプライマリスレッドによって生成されるため,基本的にプライマリスレッドグループに属する.

    ねじグループ名の取得


    現在のスレッドが属するスレッドグループの名前を取得するには、次のコードを使用します.
    ThreadGroup group = Thread.currentThread().getThreadGroup();
    String groupName = group.getName();
    Threadの静的メソッドgetalStackTraces()は、プロセスで実行されるすべてのスレッドに関する情報を取得できます.
    Map<Thread, StackTraceElement[]> map = Thread.getAllStackTraces();

    ねじグループの作成

    ThreadGroup tg = new ThreadGroup(String name);
    
    ThreadGroup tg = new ThreadGroup(ThreadGroup parent, String name);
    ねじグループの作成時に親ねじグループが指定されていない場合は、現在のねじが属するねじグループのサブグループとして作成されます.
    新しいねじグループを作成した後、そのグループにねじを含める場合は、Threadオブジェクトの作成時に構造関数のパラメータとしてねじグループを指定できます.

    スレッドグループバッチ割込み()


    スレッド・グループを使用すると、グループ内のすべてのスレッドを一括して中断するのではなく、グループ内のすべてのスレッドを一括して中断できます.
    スレッドグループの割り込みメソッドは、グループに属するスレッドの割り込みメソッドを内部で呼び出すためです.

    スレッドプール


    パラレル処理が多ければ多いほど、スレッド数が高くなり、対応するスレッドの作成とスケジューリングが忙しくなり、メモリ使用量が増加します.
    これにより、アプリケーションのパフォーマンスが低下します.
    突然のパラレルジョブの爆発を防ぐためには、スレッドプールを使用する必要があります.
    スレッドプールは、タスクを処理するために使用されるスレッドの数を制限し、ワークキューに入るタスクをスレッドごとに処理します.
    したがって、タスク処理要求が急増しても、スレッドの合計数は変わらないため、アプリケーションのパフォーマンスには影響しません.
    JAvaはjavaですutil.Concurrent Packageには、ExecutorsインタフェースとExecutorsクラスがあります.
    アクチュエータの様々な静的方法を使用して、実行サービス実装オブジェクトを作成することができる.
    これがスレッドプールです.
    (ExecuterServiceインプリメンテーションオブジェクト==スレッドプール)

    スレッドプールの簡単な作成


    ねじプールを作成するには、次の2つの方法のいずれかを使用します.

    初期ねじ数は、ねじプールを作成するときに生成されるねじ数です.
    コアスレッド数は、スレッドプールで少なくとも保持するスレッド数です.
    最大スレッド数は、スレッドプール管理の最大スレッド数です.
    newFixedThreadPoolのように、必要なスレッド数がカーネルスレッド数より大きい場合は、新しいスレッドを作成してタスクを処理します.
    初期、カーネルスレッド数を直接設定する場合は、ThreadPoolExecutorオブジェクトを作成します.
    ExecutorService threadPool = new ThreadPoolExecutor (
    	3, // 코어 스레드 수
    	100, // 최대 스레드 수
    	120L, // 놀고 있는 시간
    	TimeUnit.SECONDS, // 놀고 있는 시간 단위
    	new SynchronousQueue<Runnable>() // 작업 큐
    );

    スレッドプールを終了


    スレッドプール内のスレッドはデフォルトではデーモンスレッドではないため、メインスレッドが終了してもタスクを処理するために実行されます.
    したがって、main()メソッドが実行されても、アプリケーションプロセスは終了しません.
    アプリケーションを終了するには、スレッドプールを閉じて、スレッドを閉じた状態にする必要があります.
  • shutdown():スレッドの残りの作業を完了し、終了します.
  • shutdownNow():スレッドを強制的に閉じます.
  • 次のレポートでは、タスクの作成方法、スレッドプールへの処理の要求方法、および処理結果の受信方法について説明します.