개발 수업/JAVA

[java] 멀티 스레드/스레드(thread)

오늘 하루s 2023. 5. 24. 20:24
728x90
더보기

Day19-2. 230524

멀티 스레드

  • 프로세스 : 운영체제에서 실행 중인 하나의 애플리케이션

-> 사용자가 애플리케이션을 실행하면 운영체제로부터 실행에 필요한 메모리를 할당받는다.

- 여러 개의 프로세스가 동시에 실행될 수 있다.
- 각 프로세스는 독립적인 메모리 공간을 가지고 있다.
- 특정 프로세스에 발생한 오류가 다른 프로세스에 영향을 주지 않음.

 

스레드(thread)

스레드란?

프로세스 내부에서 코드의 실행흐름.

 

-> 작업 단위
- 한 프로세스는 여러 개의 스레드를 가질 수 있다. 이 스레드들은 동일한 메모리 공간을 공유한다.
 한 스레드가 변경한 데이터는 다른 스레드들에게도 영향을 준다.
 
- 운영체제는 두 가지 이상의 작업을 동시에 처리하는 멀티태스킹을 할 수 있도록
 CPU 및 메모리 자원을 프로세스마다 적절히 할당하고, 병렬로 실행시킨다.

 

-운영체제는 두 가지 이상의 작업을 동시에 처리하는 멀티태스킹을 할 수 있도록
CPU 및 메모리 자원을 프로세스마다 적절히 할당하고, 병렬로 실행시킨다.

 

Thread 클래스로부터 직접 생성

java.lang.Thread 클래스로부터 작업 스레드 객체를 직접 생성하려면 Runnable을 매개값으로 갖는 생성자를 호출해야함.

Thread thread = new Thread(Runnable target);

- Runnable : 작업스레드가 실행할 수 있는 코드를 가지고 있는 객체

인터페이스 타입이기 때문에 구현 객체를 만들어 대입해야함.

 

다음과 같이 Runnable 구현 클래스 작성.

class Task implements Runnable{
    public void run(){
        스레드가 실행할 코드;
  }
}

Runnable 구현 객체를 생성한 후, 이것을 매개값으로 해서 Thread 생성자를 호출해야 비로서 작업 스레드가 생성됨.

Runnable task = new Task();
Thread thread = new Thread(task);
Thread thread = new Thread (new Runnable(){
   public void run(){
     스레드가 실행할 코드;
   }
});

작업 스레드는 start() 메소드를 호출하면 실행됨.

start() 메소드가 호출되면, 작업 스레드는 매개값으로 받은 Runnable의 run()메소드를 실행하면서 자신의 작업을 처리.

thread.start();

 

 

메인 스레드만 이용되는 경우>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package chap12;
 
import java.awt.Toolkit;
 
public class BeepPrint {
 
    public static void main(String[] args) {
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        for(int i=1;i<6;i++) {
            toolkit.beep();
            try {
                Thread.sleep(250);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
        for(int i=1;i<6;i++) {
            System.out.println("beep음 소리");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        for(int i=1;i<6;i++) {
            System.out.println("출력");
        }
    }
 
}
 
cs
더보기

* 실행 결과

 

beep음 소리
beep음 소리
beep음 소리
beep음 소리
beep음 소리
출력
출력
출력
출력
출력

 

Runnable 인터페이스를 구현한 클래스>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package chap12;
 
import java.awt.Toolkit;
 
public class BeepTask implements Runnable {
 
    @Override
    public void run() {
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        for(int i=1;i<6;i++) {
            toolkit.beep();
            System.out.println("사운드재생");
            try {
                Thread.sleep(700);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
 
}
cs

 

멀티스레드(multi thread): 하나의 프로세스에서 여러 개의 thread가 동시에 실행되는 것 
 예) 미디어플레이어 : 사운드재생과  영생재생이  동시에 실행


메인스레드와 작업스레드(BeepTask)가 동시 실행>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package chap12;
 
public class BeepPrintMain {
 
    public static void main(String[] args) {
        
        Runnable beepTask = new BeepTask_p526();
       Thread thread = new Thread(beepTask);//스레드 생성
        thread.start();
         
        for(int i=1;i<6;i++) {
            System.out.println("영상재생");
            try {
                Thread.sleep(700);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
 
}
 
cs

 

더보기

* 실행 결과

 

영상재생
사운드재생
영상재생
사운드재생
영상재생
사운드재생
영상재생
사운드재생
영상재생
사운드재생

 

Thread 하위 클래스로부터 생성

작업 스레드가 실행할 작업을 Runnable로 만들지 않고,

Thread의 하위 클래스로 작업 스레드를 정의하면서 작업 내용을 포함시킬 수 있다.

 

작업 스레드 클래스 정의 방법>

 public class WorkerThread extends Thread{
  @Override
  public void run(){
    스레드가 실행할 코드; 
  }  //run() 메소드 재정의
}
Thread thread = new WorkerThread();
Thread thread = new Thread(){
  public void run(){
    스레드가 실행할 코드; 
  } //익명의 자식 객체
};

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package chap12;
 
import java.awt.Toolkit;
 
public class BeepTask2 extends Thread {
 
    @Override
    public void run() {
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        for(int i=1;i<6;i++) {
            toolkit.beep();
            try {
                Thread.sleep(700);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
cs

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package chap12;
 
public class BeepPrintMain2_p529 {
 
    public static void main(String[] args) {
        
        Thread thread = new BeepTask2_p529();//스레드 생성
        thread.start(); //Thread클래스의 run()호출
         
        for(int i=1;i<6;i++) {
            System.out.println(i+"영상재생");
            try {
                Thread.sleep(700);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
cs

 

스레드의 이름

직접 생성한 스레드는 자동적으로 "Thread-n"이라는 이름으로 설정 됨.

Thread-n 대신 다른 이름으로 설정하고 싶다면 Thread 클래스의 setName() 메소드로 변경하면 됨.

thread.setName("스레드 이름");

스레드 이름을 알고 싶을 경우 getName() 메소드를 호출

thread.getName();

 

스레드 객체의 참조를 가지고 있지 않다면 Thread클래스의 정적 메소드인 currentThread()를 이용해 현재 스레드의 참조를 얻을 수 있음.

Thread thread = Thread.currentThread();

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package chap12;
 
public class ThreadName_p531 {
 
    public static void main(String[] args) {
        //현재 스레드 얻기
        Thread mainTread= Thread.currentThread();
        System.out.println("현재 스레드 이름:"+mainTread.getName());  //main
        
        Thread ta = new ThreadA();
        System.out.println("스레드 이름:"+ta.getName());
        ta.start();
        System.out.println();
        
        Thread tb = new ThreadB();
        System.out.println("스레드 이름:"+tb.getName());
        tb.start();
        System.out.println();
        
        Thread tc = new ThreadB();
        System.out.println("스레드 이름:"+tc.getName());
        tc.start();        
    }
}
cs
더보기

* 실행 결과

현재 스레드 이름:main
스레드 이름:ThreadA

스레드 이름:Thread-1

스레드 이름:Thread-2
ThreadA이라는 이름을 가진 스레드가 실행중
ThreadA이라는 이름을 가진 스레드가 실행중
ThreadA이라는 이름을 가진 스레드가 실행중
ThreadA이라는 이름을 가진 스레드가 실행중
ThreadA이라는 이름을 가진 스레드가 실행중
Thread-1이라는 이름을 가진 스레드가 실행중
Thread-1이라는 이름을 가진 스레드가 실행중
Thread-1이라는 이름을 가진 스레드가 실행중
Thread-2이라는 이름을 가진 스레드가 실행중
Thread-1이라는 이름을 가진 스레드가 실행중
Thread-1이라는 이름을 가진 스레드가 실행중
Thread-2이라는 이름을 가진 스레드가 실행중
Thread-2이라는 이름을 가진 스레드가 실행중
Thread-2이라는 이름을 가진 스레드가 실행중
Thread-2이라는 이름을 가진 스레드가 실행중

 

ThreadA 클래스>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package chap12;
 
public class ThreadA extends Thread {
 
    public ThreadA() {
        setName("ThreadA"); //스레드에 이름 설정
    }
 
    public void run() {
        for(int i=1;i<6;i++) {
            String name = getName(); //스레드의 이름 가져오기
            System.out.println(name + "이라는 이름을 가진 스레드가 실행중");
            }
    }    
}
cs

 

ThreadB 클래스>

1
2
3
4
5
6
7
8
9
10
11
package chap12;
 
public class ThreadB extends Thread {
 
    public void run() {
        for(int i=1;i<6;i++) {
            String name = getName(); //스레드의 이름 가져오기
            System.out.println(name + "이라는 이름을 가진 스레드가 실행중");
            }
    }    
}
cs
728x90