멀티코어 컴퓨팅 6,7주차

곽태욱·2020년 5월 9일
1

강의 노트

목록 보기
20/22

자바 스레드 프로그래밍

자바엔 스레드 라이브러리가 내장되어 있다. 왜냐하면 자바 프로그램이 실행되면 JVM이 public static void main(String[] args) 메소드를 실행하는 스레드를 생성하기 때문이다.

Thread 클래스

import java.lang.Thread;

public class Main {
    // Thread.sleep() 메소드 예외 처리
    public static void main(String[] args) throws InterruptedException {
        // 스레드 객체 생성
        MyThread t1 = new MyThread("MyThread1");
        MyThread t2 = new MyThread("MyThread2");

        // 스레드 실행
        t1.start();
        t2.start();

        for (int i = 100; i < 105; i++) {
            System.out.println("main thread: " + i);
            Thread.sleep(500);
        }
    }
}

class MyThread extends Thread {
    // 스레드에 이름 부여
    MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(getName() + ": "+ i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

  1. Thread 클래스를 상속받은 MyThread 클래스에 run() 메소드를 구현한다.

  2. MyThread 클래스의 객체를 생성하고 그 객체의 start() 메소드를 호출한다.

  3. start() 메소드 뒤의 코드와 run() 메소드 코드가 동시에 실행되고, 실행 결과는 위와 비슷할 것이다. 중요한 점은 총 3개의 for문이 동시에 실행되고 있다는 점이다(main()의 for문과 run()의 for문 2개).

Runnable 인터페이스

import java.lang.Runnable;
import java.lang.Thread;

public class Main {
    public static void main(String[] args) {
        // 스레드 객체 생성
        Thread t1 = new Thread(new MyRunnable());
        Thread t2 = new Thread(new MyRunnable());

        // 스레드 실행
        t1.start();
        t2.start();

        for (int i = 100; i < 105; i++) {
            System.out.println("main thread: " + i);

            // 0.5초 대기
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println("Runnable Thread: " + i);

            // 0.5초 대기
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

  1. Runnable 인터페이스의 run() 메소드를 구현한 MyRunnable 클래스를 만든다.

  2. MyRunnable 클래스의 객체를 생성하고 Thread 클래스의 생성 인자로 넘겨준다.

  3. Thread 클래스 객체의 start() 메소드를 실행한다.

  4. start() 메소드 뒤의 코드와, MyRunnable 클래스의 run() 메소드 코드가 실행된다.

Thread.join()

public class Main {
    public static void main(String[] args) {
        // 스레드 객체 생성 및 실행
        Thread t1 = new Thread(new MyRunnable());
        t1.start();

        for (int i = 100; i < 105; i++) {
            System.out.println("main thread: " + i);
        }
        
        System.out.println("Waiting for the t1 to be finished...");
        try {    
            t1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("t1 was finished");
    }
}

위 그림과 같이 t1.join() 메소드는 t1 스레드의 실행이 끝날 때까지 현재 스레드(메인 스레드)의 실행을 일시정지하는 메소드다. 주로 데이터 동기화나 스레드의 실행 순서를 조정할 때 사용한다.

MyRunnable 클래스는 이전에 작성한 클래스를 그대로 사용했다.

Thread.sleep()

해당 스레드를 특정 시간만큼 일시정지한다.

synchronized

이 키워드가 붙은 메소드엔 1개의 스레드만 접근할 수 있다. 주로 공유자원에 접근하는 메소드에 이 키워드를 붙여 메소드 전체를 critical section으로 만든다.

wait() notify()

멀티스레딩 예제

적분

소수 개수 세기

행렬 계산

생산자 소비자 모델

생산자 스레드

작업 큐에 작업을 넣는 스레드로서 작업 큐가 가득 차 있으면 자신은 자고, 자고 있는 소비자를 모두 깨우는 역할을 한다.

소비자 스레드

작업 큐의 작업을 소비하는 스레드로서 작업 큐가 비어 있으면 자신은 자고, 자고 있는 생산자를 모두 깨우는 역할을 한다.

profile
이유와 방법을 알려주는 메모장 겸 블로그. 블로그 내용에 대한 토의나 질문은 언제나 환영합니다.

0개의 댓글