프로세스와 스레드
>>
프로세스 Process
- 운영체제로부터 자원을 할당받은 작업의 단위로, 실행중인 하나의 프로그램을 의미한다.
- 리소스(resource)와 스레드(thread)로 구성된다.
- Code, Data, Heap, Stack영역으로 이루어지며, 각각의 메모리 공간을 차지한다.
- 동시에 두 개 이상의 프로그램을 특정 기법으로 동시에 실행시키는 기능을 멀티 태스킹(multitasking) 이라 한다. 특정 기법에는 대표적으로 시분할(Time-Shared)기법이 있다.
스레드 Thread
- 프로세스 내에서 실행되는 흐름의 단위이다. 즉, 프로세스가 할당 받은 자원을 이용하는 실행 단위(흐름)이다.
- 스레드는 프로세스 내에 존재하며, 모든 프로세스는 적어도 하나이상의 스레드를 가지고 있다.
- 프로세스는 자신만의 메모리 공간과 자원을 할당받아 사용하지만, 스레드는 다른 스레드와 메모리와 자원을 공유한다.
Code, Data, Heap 영역은 공유하고 별도의 Stack영역만 가지고 있다.
- 둘 이상의 스레드를 가진 프로세스를 멀티 스레드 프로세스(multi-thread process)라 한다.
멀티 스레드
장점
- 시스템의 자원소모가 줄어든다.
- CPU의 사용률을 향상시킨다.
- 프로그램의 응답 시간이 단축된다.
단점
- 자원 공유를 위해 전역변수를 이용하므로 동기화 관련된 문제가 발생할 수 있다.
- 잘못된 변수를 사용하거나 미묘한 시간차로 인해 프로그램에 오류가 발생할 수도 있다.
- 디버깅이 어렵다.
스레드 구현 및 실행
>>
자바 메인 스레드
- 자바는 프로그램(process)이 시작되면 기본적으로 main() 메소드를 진입점(Entry Point)으로 하는 메인 스레드(Main Thread)가 생성되며, 사용자가 정의한 스레드를 생성함으로써 멀티 스레드를 구현할 수 있다.
- main()메소드는 프로그램의 진입점이지 종료점이 아니므로, 멀티 스레드 환경에서는 모든 스레드가 종료되야 프로세스가 종료된다.
java.lang.Thread 클래스
- 스레드 생성 및 시작, 관리를 위한 클래스이다.
- Thread 클래스를 상속 받은 하위 클래스에서 run() 메소드를 재정의하여 스레드를 구현한다.
java.lang.Runnable 인터페이스
- 스레드에서 실행할 코드를 가지는 run() 메소드가 선언되어 있다.
- 자바는 단일 상속만 구현 가능하므로 스레드를 구현할 클래스가 다른 클래스를 상속 받은 경우 Runnable 인터페이스를 구현한다.
- Runnable 인터페이스를 implements 한 클래스는 run() 메소드를 재정의하여 스레드를 구현한다.
스레드 시작
- 스레드를 실행하기 위해서는 Thread 클래스의 start() 메소드를 호출하면 스레드를 시작한다. start() 메소드에 의해 스레드가 시작되면, 자바 가상 머신은 이 스레드의 run() 메소드를 호출한다.
- 스레드 시작 방법
1) Thread 클래스를 상속받는 하위 클래스 만든 경우 : 해당 클래스의 객체를 생성한 후 Thread 클래스의 start() 메소드를 호출한다.
2) Runnable 인터페이스를 구현하여 클래스를 만든 경우 : Thread(Runnable target) 생성자에 Runnable 인터페이스 구현 클래스 객체를 인수로 넘겨 Thread 클래스의 객체를 생성하여 Thread 클래스의 start() 메소드를 호출한다.
스레드 종료
- 스레드의 종료는 run() 메소드가 종료되는 시점이다.
- Thread 클래스의 stop() 메소드를 이용하여 강제로 스레드를 종료할 수 있지만 사용을 권장하지 않는다.
스레드 예제
Ex001_Thread : Thread 클래스를 이용한 스레드 구현 >>
package threadEx;
public class Ex001_Thread {
public static void main(String[] args) {
MyThread1 t = new MyThread1();
t.start(); // 스레드 시작
// t.run(); // 유저가 부르면 Tread가 아님.
try {
for (int i = 1; i <= 10; i++) {
System.out.println("main -> " + i);
Thread.sleep(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main 종료 !!!");
// main은 프로그램의 시작점이지만 종료점은 아니다.
// main이 종료되어도 프로그램은 종료되지 않을 수 있다.
// 프로그램의 종료 시점은 모든 독립스레드가 종료되는 시점이다.
}
}
// 스레드 구현방법 - 1
// 1) Thread 클래스를 상속 받아 run() 메소드를 override한다.
// 2) Thread 클래스를 상속 받은 클래스의 객체를 생성하여 start() 메소드를 호출한다.
class MyThread1 extends Thread {
@Override
public void run() {
int n = 0;
try {
while (n < 20) {
n++;
System.out.println(getName() + " -> " + n);
sleep(500); // 지정 시간(단위:ms)동안 스레드 실행이 일시 중지됨.
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
스레드클래스를 상속받아 run() 메소드를 override 해서 클래스의 객체를 생성해서 start()메소드로 멀티 스레드를 구현했다. main 에서도 이미 Thread가 (main() 메소드를 진입점으로 하는 메인 스레드가 존재) 있기 때문에 둘을 비교해보았다.
![](https://blog.kakaocdn.net/dn/bd1xkn/btreh1kvk6j/iOCjktNveJuLOKNAas54dk/img.png)
main()이 종료되어도 프로그램 종료는 모든 독립 스레드가 종료된 후에 일어난다.
Ex002_Runnable : Runnable 인터페이스를 이용한 스레드 구현 >>
package threadEx;
public class Ex002_Runnable {
public static void main(String[] args) {
MyThread2 th = new MyThread2();
Thread t = new Thread(th);
t.start();
try {
for (int i = 1; i <= 10; i++) {
System.out.println("main -> " + i);
Thread.sleep(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main 종료 !!!");
}
}
// 스레드 구현방법 - 2
// 1) Runnable 인터페이스를 구현하는 클래스를 만들어 run() 메소드를 override 한다.
// 2) Runnable 인터페이스 구현 클래스 객체를 생성한다.
// 3) Thread 클래스를 객체를 생성하며, Thread 객체를 생성할 때 생성자의 인자에 2)번에서 생성한 객체를 넘긴다.
// 4)
class MyThread2 implements Runnable {
@Override
public void run() {
int n = 0;
try {
while (n < 20) {
n++;
System.out.println(Thread.currentThread().getName() + " -> " + n);
Thread.sleep(500);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Runnable 인터페이스를 구현하는 클래스를 만들어 run() 메소드를 override한 후 Runnable 인터페이스 구현 클래스 객체를 생성한다. Thread 클래스 객체를 생성하여 생성자의 인자에 Runnable 구현 클래스 객체를 넘겨준다.
![](https://blog.kakaocdn.net/dn/bze2N5/btrelRnUpDT/cINUTE5CczOvrEVnPdjIpk/img.png)
Ex003_Runnable : 익명 클래스를 이용한 스레드 구현 >>
package threadEx;
public class Ex003_Runnable {
public static void main(String[] args) {
// 스레드 구현방법 - 3 : 익명 클래스를 이용한 스레드 구현
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
for (int n = 1; n <= 20; n++) {
System.out.println("스레드 -> " + n);
Thread.sleep(500);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
try {
for (int i = 1; i <= 10; i++) {
System.out.println("메인 -> " + i);
Thread.sleep(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("메인 종료 !!!");
}
}
익명클래스는 전에 수업시간에 한 번 보고 나서 너무 오랫만에 보는 클래스라 너무 낯설었다.
![](https://blog.kakaocdn.net/dn/cqLH7F/btrea1eZpIN/KteHrK4VNcyvCzg3u0gGAK/img.png)
Ex004_Runnable : 람다를 이용한 스레드 구현 >>
package threadEx;
public class Ex004_Runnable {
public static void main(String[] args) {
// 스레드 구현 방법 - 4 : 람다를 이용한 스레드 구현
Thread t = new Thread( () -> {
try {
for (int n = 1; n <= 20; n++) {
System.out.println("스레드 -> " + n);
Thread.sleep(500);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t.start();
try {
for (int i = 1; i <= 10; i++) {
System.out.println("메인 -> " + i);
Thread.sleep(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("메인 종료 !!!");
}
}
람다는 아직 배우지 않았으므로 그냥 이렇게 구현할 수 있구나~ 정도만 알면 된다고 하셨다.
![](https://blog.kakaocdn.net/dn/bvOpSZ/btrejWXjKyB/XgH71PJik8DTzz0QQViikK/img.png)
'쌍용강북교육센터 > 9월' 카테고리의 다른 글
0903_Java : Daemon Thread (0) | 2021.09.07 |
---|---|
0903_Java : Thread 클래스 활용 예제 (0) | 2021.09.07 |
0902_데이터 모델링 및 설계 (0) | 2021.09.03 |
0902_Java : JDBC : 자바로 SQLPlus와 비슷한 프로그램 짜기 (0) | 2021.09.02 |
0901_Java : JDBC : Metadata 메타데이터 (0) | 2021.09.02 |