2022/02/26 Javaの各種機能


JavaでのThreadの作成
Threadとは?
  • プロセス:(アプリケーションがメモリを占有)実行するアプリケーションが実行されると、オペレーティングシステムからメモリが割り当てられ、プロセスステータス
  • に移行します.
  • thread:プロセスには1つ以上のスレッドがあり、実際の操作を実行する単位はthreadです.
  • multi-threading
  • マルチスレッド同時プログラミング、マルチタスク同時効果
  • threadはそれぞれ自分のワークスペース(コンテキスト)
  • を持っている.
  • スレッド間でリソース(Javaでは静的インスタンス)
  • を共有できます.
  • 複数のスレッドがリソースを共有してタスクを実行する場合、競合が発生する可能性があります
  • .
  • 複数のスレッドが共有するリソースで競合する部分をキー部分
  • と呼ぶ.
  • キー部分に同期を実施しない場合(シーケンス実行)、エラー
  • が発生する可能性があります.

    Thread Status

    Thread起動後、ThreadはThreadPoolに入り、Runable状態になります.Thread終了時をDeadと呼びます
    Not Runnable状態ではCPUを占有することはできませんが、Javaではsleep(時間)、wait()の3つの方法があり、リソースが限られています.複数のスレッドが存在する場合、有効なThread->NotRunnableが待機し、リソースが有効な場合、プログラムがnotify()を実行すると、1つのスレッドのみが実行されます.(notifyall()はすべて)join()は別のスレッドに掛けられ、自分はNot Runable状態に陥り、他のスレッドが終了すると自分はRunableになります.
    Threadクラスのさまざまな方法
    Thread優先度
  • Thread.MIN_PRIORITY(=1)~Thread.MAX_PRIORITY(=10)
  • デフォルト優先度:Thread.NORMAL_PRIORITY(=5)
  • より優先度の高いThreadは、CPU割り当てを取得する確率がより高い(最初に実行するのではなく確率がより高い)
  • を得る.
  • setPriority()/getPriority()
  • join()
    2つ以上のThreadを同時に実行する場合、別のThreadの結果を参照して実行する必要がある場合は、join()関数を使用します.
  • join()関数を呼び出すThreadプラスnot-runnableステータスは
  • です.
  • 他のThreadが完了するとrunnable状態
  • に戻る.

    2つのThreadを作成し、
  • 1から50、51から100の和を求め、結果を検証します:
  • public class JoinTest extends Thread {
    
        int start;
        int end;
        int total;
    
        public JoinTest(int start, int end) {
            this.start = start;
            this.end = end;
    
        }
    
        public void run() {
    
            int i;
            for (i = start; i <= end; i++) {
                total += i;
            }
        }
    
        public static void main(String[] args) {
    
            JoinTest jt1 = new JoinTest(1, 50);
            JoinTest jt2 = new JoinTest(51, 100);
    
            jt1.start();
            jt2.start();
    
            try {
                jt1.join();
                jt2.join();
    
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            int lastTotal = jt1.total + jt2.total;
            System.out.println("jt1.total = " + jt1.total);
            System.out.println("jt2.total= " + jt2.total);
            System.out.println("합계 : " + lastTotal);
    
    
        }
    
    }
    interrupt()
  • 他のThreadに異常を送信割り込み
  • .
  • Threadがjoin()、sleep()、wait()関数によってnot-runnableとして呼び出されると、iterrupt()メソッドを呼び出すとrunnable状態
  • に再び戻ることができる.
    終了
  • Thread終了時に使用する
  • 無限ループの場合、while(flag)のflag変数値はfalseになり、
  • を終了する.
    終了
  • Thread例
  • マルチスレッドプログラミングでの同期
    臨界領域と信号量
  • 臨界領域は、2つ以上のスレッドが同時にアクセスすると問題が発生する可能性があるため、同時にアクセスできない領域
  • です.
  • 信号量は、get/releaseの2つの機能を有する特殊な形式のシステムオブジェクトである.
  • は、一瞬にして1つのスレッドだけが信号量を得ることができ、残りのスレッドは待機(ブロック)状態
  • にある.
  • 信号量を得るスレッドのみが臨界領域に入る.
  • ParkとParkWifeが同時に銀行リソースにアクセスして動作を完了する例
  • class Bank {
        private int money = 10000;
    
        public void saveMoney(int save) {
    
            int m = getMoney();
    
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            setMoney(m + save);
    
        }
    
        public void minusMoney(int minus) {
    
            int m = getMoney();
    
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            setMoney(m - minus);
        }
    
        public int getMoney() {
            return money;
        }
    
        public void setMoney(int money) {
            this.money = money;
        }
    }
    
    class Park extends Thread {
    
        public void run() {
            System.out.println("start save");
            SyncMain.myBank.saveMoney(3000);
            System.out.println("saveMoney(3000) :   " + SyncMain.myBank.getMoney());
        }
    }
    
    class ParkWife extends Thread {
    
        public void run() {
            System.out.println("start minus");
            SyncMain.myBank.minusMoney(1000);
            System.out.println("minusMoney(1000) :   " + SyncMain.myBank.getMoney());
        }
    }
    
    
    public class SyncMain {
    
        public static Bank myBank = new Bank();
    
        public static void main(String[] args) throws InterruptedException {
    
            Park p = new Park();
            p.start();
    
            Thread.sleep(200);
    
            ParkWife pw = new ParkWife();
            pw.start();
    
    
        }
    }
    こうすれば.


    このようなマルチスレッドが2つある場合は共有リソースを使用し、1つのスレッドが共有リソースを使用している場合は別のスレッドが共有リソースを使用している場合は、共有リソースを変更することはできません.
    変更されたコード
    class Bank {
        private int money = 10000;
    
        public synchronized void saveMoney(int save) {
    
            int m = getMoney();
    
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            setMoney(m + save);
    
        }
    
        public synchronized void minusMoney(int minus) {
    
            int m = getMoney();
    
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            setMoney(m - minus);
        }
    
        public int getMoney() {
            return money;
        }
    
        public void setMoney(int money) {
            this.money = money;
        }
    }
    
    class Park extends Thread {
    
        public void run() {
            System.out.println("start save");
            SyncMain.myBank.saveMoney(3000);
            System.out.println("saveMoney(3000) :   " + SyncMain.myBank.getMoney());
        }
    }
    
    class ParkWife extends Thread {
    
        public void run() {
            System.out.println("start minus");
            SyncMain.myBank.minusMoney(1000);
            System.out.println("minusMoney(1000) :   " + SyncMain.myBank.getMoney());
        }
    }
    
    
    public class SyncMain {
    
        public static Bank myBank = new Bank();
    
        public static void main(String[] args) throws InterruptedException {
    
            Park p = new Park();
            p.start();
    
            Thread.sleep(200);
    
            ParkWife pw = new ParkWife();
            pw.start();
    
    
        }
    }
    同期(synchronization)
    2つのスレッドが同じオブジェクトに同時にアクセスすると、エラーが発生します.
  • 同期は共有リソースをロックし、他のスレッドへのアクセスを制御する
  • 問題は、
  • の同期が正しく実現されなければ、デッドロックに陥る可能性があることである.
  • Java synchronizedメソッドまたはsynchronizedブロックの使用
    どうきブロック
  • 現在のオブジェクトはロックまたは他のオブジェクトになります.
  • synchronized(참조형 수식) {
    
          수행문;
    }
    
    同期メソッド
  • オブジェクトのメソッドで同期キー
  • を使用する.
  • 現在このメソッドが属するオブジェクトロック
  • Javaはデッドロックを防止する技術を提供しないので、同期方法で他の同期方法
  • を呼び出すことは許されない.
  • デッドロックの例
  • wait()/notify()メソッドによる同期プログラミング
  • リソースがいくつかの条件下で有効でない場合、Threadはリソースを待つためにwait()状態になります.
  • wait()状態のThreadはnotify()呼び出しを待つ.
  • の有効なリソースがある場合、notify()が呼び出され、wait()のThreadでランダムにThreadが再起動されます.
  • notifyAll()が呼び出されると、待機中のすべてのThreadが再起動されます.
  • の場合、有効なリソースと同じThreadしか実行できず、リソースがない場合はwait()状態に再設定されます.
  • Java推奨notifyAll()メソッド
  • 図書館借書例