JAva 23(プロセスとスレッド、マルチスレッド)

36150 ワード

Background: processes and threads


コンピュータを開いてプログラムを実行すると、オペレーティングシステムにプロセスが作成されます.プロセスは、プログラムを迂回するためにリソースを割り当てます.この場合、オペレーティングシステムは各プログラムにメモリを割り当てる責任を負い、メモリが最も重要です.

したがって、タスクマネージャを実行すると、プログラムごとにどれだけのメモリが割り当てられているかを決定できます.
スレッド:プログラムを実行する最小ユニットで、スケジューラによって独立して管理されます.各プロセスには、少なくとも1つのスレッドから複数のスレッドがあります.したがって、プロセスに2つのスレッドがある場合は、マルチスレッドプロセスと呼ばれます.

画像のようにプロセスを表示すると、1つのスレッドに数十個のスレッドが存在する可能性があります.また、リソース(メモリ)も一緒にプロセスに入ります.
したがって,複数のプロセスとファジイスレッドがプロセスに存在するのは異なる概念である.

Background: multitasking vs. multithreading


  • Multitasking
    オペレーティングシステムは同時に複数のプロセスを実行します.Concurrently
    現代のオペレーティングシステムはマルチタスク処理をサポートしています.

  • Multithreading
    1つのプロセスで複数のスレッドを使用して同時に回転します.

  • だから左図を見るとマルチタスク処理で、右図はマルチスレッド処理です.

    Background: multithreading

  • の利点
  • リソースを有効に使用します.1つのプログラムが複数のトランザクションを処理する必要がある場合、スレッドが多い場合は、複数のスレッドを同時に処理できます.
  • サーバが複数のクライアントにサービスを提供する場合、複数のスレッドがある場合、複数のクライアントにサービスを提供できます.
  • は、タスクによってスレッドを分割することによってプログラムをモジュール化する機能モジュールと呼ばれる.
  • の欠点
  • 同期:2つのスレッドが1つのメモリに同時にアクセスすると競合する可能性があります.
  • Dead lock:AスレッドCリソースはDリソースを必要とし、BスレッドはDリソースを必要とする場合、両方のスレッドは自分の欲しいリソースが取得できないためプログラムが停止する.
  • Inefficiency:スレッドが作成されているが、プログラマが操作を実行させない場合、
  • Implementing threads in Java


    Javaではthreadをclassとして作成するため、それを継承したりinterface runnableを取得したりする方法があります.
    class MyThread extends Thread {
    	public void run() { // overriding
    		/* tasks to run on a thread */
    	}
    }
    
    class MyThread implements Runnable {
    	public void run() {
    		/* tasks to run on a thread */
    	}
    }
    ThreadクラスまたはRunnable abstractクラスを受信すると、上記のようなrunという関数が生成されます.ここに私たちが望んでいる仕事を書くことです.

    Implementing threads in Java: Example

    
    //thread를 상속받아서 getName을 반복해서 출력해 주고 있다.
    class ThreadEx1_1 extends Thread {
    	public void run() {
    		for(int i=0; i<5; i++) System.out.println(getName());
    	}
    }
    
    //여기에서는 Thread에 있는 함수를 사용할 수 없어서 Thread 클래스로 부터 currentThread를 받아와야 한다.
    class ThreadEx1_2 implements Runnable {
    	public void run() {
    		for(int i=0; i<5; i++) System.out.println(Thread.currentThread().getName());
    	}
    }
    では、なぜ上と一緒にやるのでしょうか.これは,複数の継承から継承を得ることができないため,クラスとして継承するクラスにスレッドを加えるにはRunableしか得られない.
    したがって、異なるクラスを受信した各クラスは、次のように記述され、実行できます.
    public class Lecture {
    	public static void main(String[] args) {
        	//Thread를 상속 받았다면 그냥 선언하면 된다.
    		ThreadEx1_1 t1 = new ThreadEx1_1();
            
            //Runnable을 상속 받았다면 우선 객체를 만든다음 스래드 객체로 넘기어 주어야 한다.
    		Runnable r = new ThreadEx1_2();
    		Thread t2 = new Thread(r);
            
            //최종적으로 start함수를 부르면 스레드가 시작된다.
    		t1.start();
    		t2.start();
    	}
    }

    以上の出力結果から,スケジューラには一定の順序がないことが分かる.
    最終的に、スレッドをスケジューラに入力してプログラムを実行するために、スケジューラは、どのスレッドをアップグレードするかを決定し、プログラムを最終的に順番に実行します.これを見ると、スケジューラはスケジューラスレッドと呼ばれます.

    Threads: start and run


    なぜrunでstartを定義して呼び出すのですか?これはcall stackのためです.

    現在call stackは以下の通りです.プログラムが実行されると、mainはまずスタックに入り、runを呼び出し、runはスタックに入り、runは実行し、mainは実行します.だからcall stackのtopは今実行しているプログラムです.
    逆にstartを呼び出すと、以下のようになります.

    startの仕事は、callスタックをもう1つ作成し、新しく作成したスタックにrunを挿入してマルチスレッドで実行することです.上図とは異なり、上図は最終的に単一Thread形式でプログラムを実行しますが、呼び出しを開始すると、私たちが望むマルチThread機能が使用されます.
    マルチコアCPUを使用しているので、マルチスレッドを使用することができます.
    このとき,2つのスレッドが同時に実行されると,どのスレッドが最初に終了するか予測できない.mainが最初に完了すると、call stackが返されますが、run付きcall stackはまだ実行中です.この場合、すべてのthreadが完了すると、プログラムも一緒に終了します.

    Threads: Example 2

    public class Lecture {
    	public static void main(String args[]) throws Exception {
    		ThreadEx2_1 t1 = new ThreadEx2_1();
    		t1.start();
    	}
    }
    
    class ThreadEx2_1 extends Thread {
    	public void run() {
    		throwException();
    	}
        
        //일부러 Exception을 발생시키어서 call stack이 어떻게 동작하는지 확인하는 부분이다.
    	public void throwException() {
    		try {
    			throw new Exception();
    		} catch(Exception e) {
            //여기에서 call stack을 확인할 수 있다.
    			e.printStackTrace();
    		}
    	}
    }
    
    public class Lecture {
    	public static void main(String args[]) throws Exception {
    		ThreadEx3_1 t1 = new ThreadEx3_1();
    		t1.run();
    	}
    }
    
    class ThreadEx3_1 extends Thread {
    	public void run() {
    		throwException();
    	}
        
    	public void throwException() {
    		try {
    			throw new Exception();
    		} catch(Exception e) {
    			e.printStackTrace();
    		}
    	}
    }

    出力結果からthrowExceptionが一番上、runがワイプバーにあることがわかります.でもどうしてmainが見えないの?これはThread呼び出しスタックを使用することによっては見えないためである.

    逆にrunを呼び出すと、上記の構成が表示されます.

    Single thread vs. multiple threads: experiment

    //아래와 같이 같은 String을 출력하는 프로그램의 시간을 측정해 보았다.
    public class Lecture {
    	public static void main(String[] args) {
    		long startTime = System.currentTimeMillis();
            
    		for(int i=0; i<300; i++) {
    			System.out.printf("%s", new String("-"));
    		}
            
    		System.out.print("elapsed time: " + (System.currentTimeMillis() - startTime));
            
    		for(int i=0; i<300; i++) {
    			System.out.printf("%s", new String("|"));
    		}
            
    		System.out.print("elapsed time: " + (System.currentTimeMillis() - startTime));
    	}
    }
    
    // 위와 유사하지만 스레드를 사용해서 같은 String을 여러번 찍도로 하였다.
    public class Lecture {
    	static long startTime = 0;
    	public static void main(String[] args) {
        	//우선 스레드를 만들고 작동시킨다.
    		ThreadEx5_1 th1 = new ThreadEx5_1();
    		th1.start();
            
    		startTime = System.currentTimeMillis();
    
    		//main에서도 어떤일을 실행시키었다.
    		for(int i=0; i<300; i++) System.out.printf("%s", new String("-"));
    		System.out.print("elapsed time 1: " + (System.currentTimeMillis() - Lecture.startTime));
    	}
    }
    
    // 이 부분이 concurrently 하게 작동한다.
    class ThreadEx5_1 extends Thread {
    	public void run() {
    		for(int i=0; i<300; i++) System.out.printf("%s", new String("|"));
    		System.out.print("elapsed time 2: " + (System.currentTimeMillis() - Lecture.startTime));
    	}
    }
    同時に存在する.CPUが1つしかない場合、スレッドはスケジューラに従って2つのスレッドを同時に実行するのではなく、1つのスレッドのみを実行します.したがって、同時に動作するのではなく、CPUを同時に上下して繰り返します.

    これは単一Threadでの動作時の時間測定であり,なぜ最初の動作に時間がかかるのか分からない.これはスケジューラに既存のタスクで、最初のタスクを実行するには時間がかかります.もう一つ確認できるのは、彼らが連続的に完成していることです.

    逆に,複数のThreadを用いた場合,測定時間が類似していることが確認できた.

    Single thread vs. multiple threads


    単線であれば、二つのことがつながって処理されます.

    ただし、AとBが異なるスレッド上で実行されている場合は、次の操作が表示されます.

    左側がsingle coreの場合、スケジューラはAとBを同時に実行します.右側に複数のcoreがある場合は、エンティティで同時に操作されます.

    Benefits of multithreading

    public class Lecture {
    	public static void main(String[] args) throws Exception {
        // java에서 Dialog 박스가 나와서 유저에게 입력을 받게 된다.
    		String input = JOptionPane.showInputDialog("Enter any string.");
    		System.out.println("You have entered: " + input);
            
            // sleep은 1000 = 1초로 1초동안 스레드가 잠시 멈추게 된다.
    		for(int i=10; i>0; i--) {
    			System.out.println(i);
    			try {
    				Thread.sleep(1000);
    			} catch(Exception e) { /* do nothing */ }
    		}
    	}
    }
    上と違ってスレッドを使った作成はどうなりますか?次はスレッドを使用するコードです.
    public class Lecture {
    	public static void main(String[] args) throws Exception {
    		ThreadEx7_1 th1 = new ThreadEx7_1();
    		th1.start();
    		String input = JOptionPane.showInputDialog("Enter any string.");
    		System.out.println("You have entered: " + input);
    	}
    }
    
    class ThreadEx7_1 extends Thread {
    	public void run() {
    		for(int i=10; i>0; i--) {
    			System.out.println(i);
    			try {
    				sleep(1000);
    			} catch(Exception e) { }
    		}
    	}
    }

    最終的には、単一スレッドでは、上図のようにAの終了を待つ.

    これとは異なり、マルチスレッドの場合、AとBは交代で動作します.その結果、2つの仕事が一緒に働くメリットが生まれました.