[java] 멀티 스레드/스레드(thread)
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 |