スレッド(thread)-(1)


スレッドに関する概念


プロセスとスレッド


プロセスとは、プログラムがメモリを割り当てて実行している状態を指し、データやメモリなどのリソースとスレッドで構成されます.
1つのプログラムは複数のプロセスを生成することができます.同じプログラムを複数回実行すると、実行回数と同じプロセスが発生します.
スレッドとは、プロセス内で実際に操作を実行する主体です.各プロセスには、アクションを実行するために少なくとも1つのスレッドが存在します.

マルチスレッドとマルチプロセス


1つのプロセス内で複数のスレッドを使用する場合をマルチスレッドプロセスと呼びます.マルチプロセスとは、複数のCPUを使用して同時に複数のプロセスを実行することです.
マルチスレッドとマルチプロセスの共通点は、複数のストリームを同時に実行することです.複数のプロセスはそれぞれ独立して実行されますが、複数のスレッドの違いは、各スレッドが属するプロセスのメモリを共有することです.

Context Switching


コンピュータが同時に処理できる最大タスク数はCPUのカーネル数です.スレッド数がカーネル数より大きい場合、各カーネルは指定した時間内に複数のタスクを交代で実行します.
Context Switchingは、カーネル内のスレッドが置き換えられたときに発生し、現在の作業状態または次のタスクに必要な様々なデータを格納および読み取ります.Contextを切り替える時間が長ければ長いほど、マルチスレッドの効率は低下します.マルチ実行スレッドは必ずしも有効ではありません.

メインスレッド(mainthread)


すべてのJavaプログラムは、JVMのメインスレッドがmainメソッドを実行することから始まります.mainの最初のコードから順に下に実行し、最後のコードを実行した後、または戻り文に遭遇したときに終了します.

マルチタスク処理


プライマリメソッドは、ワークスレッドを作成することによってコードを並列に実行できます.プライマリ・スレッドが終了したため、ワーク・スレッドは終了しません.(ただし、デーモンプロセスの場合、プライマリスレッドが終了すると、それ自体も終了します.)すなわち、プロセスは、プライマリ・スレッドと他のオペレーション・スレッドが終了している場合にのみ終了します.

同期と並列


同時


1つのカーネル内のマルチスレッドが交互に動作する性質.カーネルごとに1回に1つのスレッドしか実行できないため、性質があります.

パラレル


各カーネルでスレッドを同時に実行する性質.複数のカーネルが独立して動作し、互いに干渉しません.

ねじの作成


スレッドはRunnableインタフェースを実装するか、Threadクラスを継承することによって作成できます.誰もがrun()メソッドを上書きすることで実現できる.
別のクラスを継承するクラスをスレッドとして作成する場合は、二重継承はできませんので、Runnableインタフェースを実装することで解決する必要があります.

Threadクラスから直接作成

public class Task extends Thread{
    @Override
    public void run() {
        // 실행할 코드
    }
}

public class Main {
    public static void main(String[] args) {
        Thread task = new Task();
        task.start();
    }
}

Runnableインタフェースの実装

public class Task implements Runnable{
    @Override
    public void run() {
        // 실행할 코드
    }
}

public class Main {
    public static void main(String[] args) {
        Runnable task = new Task();

        Thread thread = new Thread(task);
        thread.start();
    }
}

匿名実装オブジェクトの使用

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                // 실행 코드
            }
        });

        thread.start();
    }
}

ラムティーを使う

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            // 실행 코드
        });
        thread.start();
    }
}

スレッドスケジューリング


スレッド数がカーネル数より大きい場合、どの順序で同時に実行するかを決定します.これらのスケジューリングに基づいて、スレッドは順番にrun()メソッドを実行します.

優先度


優先度の高いスレッドは、より多くの実行状態のスケジューリング方法を得ることができます.開発者は、各スレッドの優先度を設定することで制御できます.

循環配分


タイムスライスは、CPUが所定の時間に1つのスレッドを実行する方式である.開発者はコードで制御できない.

優先度フィールド


各スレッドには、優先度に関するフィールドがあります.この優先度に基づいて、特定のスレッドをより長く動作させるように設定できます.
フィールドの説明静的INT MAX PRORITYスレッドが持つことができる最大優先度を指定します.静的int MIN PRORITYスレッドの最小優先度を指定します.静的NORM PRORITYスレッドを作成するときのデフォルトの優先度を指定します.
スレッドの優先度は1~10で、getPriority()メソッドとsetPriority()メソッドで優先度にアクセスできます.この優先順位は比例的な節税値ではなく、課税値です.
次の例では、スレッドの優先度を10に設定して実行します.
class ThreadWithRunnable implements Runnable {
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName());
            // 현재 실행 중인 스레드의 이름을 반환함.
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class Thread02 {
    public static void main(String[] args){
        Thread thread1 = new Thread(new ThreadWithRunnable());
        Thread thread2 = new Thread(new ThreadWithRunnable());

①      thread2.setPriority(10); // Thread-1의 우선순위를 10으로 변경함.
②      thread1.start(); // Thread-0 실행
③      thread2.start(); // Thread-1 실행

        System.out.println(thread1.getPriority());
        System.out.println(thread2.getPriority());
    }
}
「Thread-1」と「Thread-0」が交互に出力されます.thread 2は優先度に比例し、実行速度はthread 1の10倍ではない.ただし、thread 2の優先度が高いため、thread 2のstartが呼び出されても、先に実行されるだけです.

スレッド内のフィールド、メソッド


スレッド名


スレッドの場合、開発者が名前を個別に設定していない場合は、自動的に名前が設定されます.メインスレッドの場合はmainに、他のスレッドの場合はThread-nに設定されます.スレッド名を受信するとgetName()が呼び出され、名前を設定するとsetName()メソッドが呼び出されます.
public class Task implements Runnable{
    @Override
    public void run() {
         System.out.println(Thread.currentThread().getName());
    }
}

public class Main {
    public static void main(String[] args) {
        Thread task = new Thread(new Task());
        task.start(); // Thread-0
    }
}

現在のトピック


現在実行されているスレッドについては、静的メソッドcurrentThread()で返すことができます.
public class Main {
    public static void main(String[] args) {
        Thread current = Thread.currentThread();
        System.out.println(current.getName()); // main

    }
}

Reference


http://tcpschool.com/java/java_thread_concept
http://tcpschool.com/java/java_thread_multi