▶ 스레드 (Thread)
1) 프로세스 (Process)
- 간단한 의미로 실행 중인 프로그램
- 프로세스는 프로그램이 실행될 때마다 개별적으로 생성
- 하나의 프로세스는 프로그램 수행에 필요한
데이터와 메모리 등의 할당 받은 자원 & 하나 이상의 스레드로 구성됨
2) 스레드 (Thread)
- 프로세스 내에서 할당된 자원을 이용해 실제 작업을 수행하는 작업 단위
- 모든 프로세스는 하나 이상의 스레드를 가지며 각각 독립적인 작업 단위를 가짐
3) 메인 스레드
- 모든 자바 프로그램은 메인 스레드가 메인 메소드( main( ) )를 실행하며 시작
- main( ) 메소드의 첫 코드부터 아래로 순차적으로 실행되고, return을 만나면 종료됨
- 필요에 의해 여러 작업 스레드를 만들어서 병렬 코드를 실행 가능(멀티 스레드를 이용한 멀티 태스킹)
4) 프로세스 종료
- 싱글 스레드인 경우, 메인 스레드가 종료되면 프로세스 종료 O
- 멀티 스레드인 경우, 실행 중인 스레드가 하나라도 있다면 프로세스 종료 X
5) 멀티 프로세스 VS 멀티 스레드
- 멀티 프로세스 : 각각의 프로세스를 독립적으로 실행하는 것
- 멀티 스레드 : 하나의 프로세스 내에서 여러 스레드가 동시에 작업을 수행하는 것
6) 싱글 스레드 VS 멀티 스레드
- 싱글 스레드 : 메인 스레드 하나만으로 작업 처리 → 한 작업씩 차례대로 처리
- 멀티 스레드 : 메인 스레드 외 추가적인 스레드를 이용하여 병렬적으로 작업 처리
7) 멀티 스레드의 장점
- 자원을 보다 효율적으로 사용
- 사용자에 대한 응답성 향상
- 어플리케이션의 응답성 향상
- 작업이 분리되어 코드 간결해짐
- CPU 사용률 향상
8) 멀티 스레드의 단점
- 동기화(Synchronization)에 주의
- 교착상태(deda-lock)가 발생하지 않도록 주의
- 프로그래밍 시 고려할 사항이 많음
9) 스레드 생성
- Thread 클래스 상속 받기
- run( ) 메소드가 추상 메소드가 아니라서 강제 오버라이딩 X
public class TestThread1 extends Thread{
// Thread.currentThread() : 현재 실행 중인 스레드를 반환
// Thread.currentThread().getName() : 현재 실행 중인 스레드의 이름 반환
@Override
public void run() {
// run() 메소드 : 스레드가 생성되어 실행( start() ) 시 수행될 구문을 작성하는 메소드
System.out.println(Thread.currentThread().getName()+" 실행");
for(int i=0; i<10; i++) {
System.out.println("0번 스레드 "+i);
}
}
}
public class TestRun {
public static void main(String[] args) {
// 방법 1. Thread 클래스 상속
TestThread1 test1 = new TestThread1();
test1.start(); // 스레드 실행
}
}
- Runnable 인터페이스 구현
- run( ) 메소드 오버라이딩이 강제됨
public class TestThread2 implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" 실행");
for(int i=0; i<10; i++) {
System.out.println("1번 스레드 "+i);
}
}
}
public class TestRun {
public static void main(String[] args) {
// 방법 2. Runnable 인터페이스 상속
// new Thread( Runnable target ) :
// - Runnable 인터페이스를 상속 받은 객체를 매개변수에 추가
Thread test2 = new Thread( new TestThread2());
test2.start();
}
}
10) run( ) / start( ) 메소드
- run( ) 호출
- start( ) 호출
11) 스레드 컨트롤
- 실행 중인 스레드 상태를 제어하기 위한 것
- 효율적이고 정교한 스케쥴링을 위한 스레드 상태를 제어하는 기능
- 주로 sleep( ), interrupt( ) 위주로 사용됨
- sleep( ) 예제
// 스레드 생성(Runnable 인터페이스 상속)
public class SleepThread1 implements Runnable{
@Override
public void run() {
for(int i=1; i<=10; i++) {
// Thread.sleep(long millis)
// - 현재 스레드를 지정된 시간만큼 일시정지
// - 시간은 1/1000초 단위(ms)
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i+"초");
}
}
}
public class MyClock implements Runnable{
@Override
public void run() {
// 00시 00분 00초 형식으로 시계 만들기
// SimpleDateFormat : 간단하게 날짜/시간 형식을 지정하는 객체
SimpleDateFormat sdf = new SimpleDateFormat("HH시 mm분 ss초");
// HH -> 시 (24시간) / mm -> 분 / ss -> 초
while(true) {
Date date = new Date(); // 현재 시간이 객체로 생성되며 저장
System.out.println(sdf.format(date));
try {
Thread.sleep(1000); // 시간 출력 후 1초 일시정지
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
- + interrupt( ) 예제
- interrupt( ) : 스레드의 동작을 방해해서 멈추게 함
- void interrupt( )
- 현재 스레드의 interrupted 필드값을 true로 변경
- interrupted 필드 == false → 작업 진행
- interrupted 필드 == true → 작업 멈춤 - boolean isInterrupted( )
- 현재 스레드의 interrupted 필드값을 반환 (getter) - boolean Thread.interrupted( )
- 현재 스레드의 interrupted 필드값을 반환
- false로 값을 변경
public class SleepThread2 implements Runnable{
@Override
public void run() {
int count = 0;
// Thread.currentThread().isInterrupted()
// 현재 스레드의 interrupted 필드 값 반환
// -> 수행 중이면 false, 멈춰야되면 true
// interrputed 필드 값이 false면 계속 반복 / true면 종료
while(!Thread.currentThread().isInterrupted()) {
try { // 0.5초마다 count를 1씩 증가하며 출력
Thread.sleep(500); // 0.5초
System.out.println(++count);
} catch (InterruptedException e) {
// sleep() 중 interrupt() 메소드가 호출되면
// InterruptedException이 발생하고
// interrupted 필드 값이 true로 변하지 못하게 된다.
// -> catch문에서 interrupted 필드 값을 true로 변경
System.out.println("=== 인터럽트에 의해서 종료 ===");
Thread.currentThread().interrupt();
}
}
}
}
/*---------------------------------------------------------*/
public class ThreadControlRun {
public static void main(String[] args) {
Thread sleepThread2 = new Thread( new SleepThread2() );
sleepThread2.start();
}
}
/*=========================================================*/
public class InterruptTest {
public void test() {
Thread sleep2 = new Thread( new SleepThread2() );
sleep2.start(); // SleepTread2의 run() 메소드 실행
System.out.println("<엔터 입력 시 종료>");
Scanner sc = new Scanner(System.in);
sc.nextLine(); // 입력 버퍼에서 다음 \n까지 읽어오기
// 단, 버퍼가 비어있으면
// 다음 \n(엔터) 입력 시까지 현재 스레드 무한 대기
// 무한 대기 중...
// 엔터 입력 시 sleep2 스레드를 멈추게 하는 interrupt() 호출
sleep2.interrupt();
}
}
/*---------------------------------------------------------*/
public class ThreadControlRun {
public static void main(String[] args) {
InterruptTest it = new InterruptTest();
it.test();
}
}
- sleep( ) + interrupt( ) 예제 - 2
public class ThreadControlRun {
public static void main(String[] args) {
StopWatchContoller stopWatch = new StopWatchContoller();
stopWatch.watchStart();
}
}
/*-----------------------------------------------------------------*/
public class StopWatchContoller {
public void watchStart(){
// StopWatch 스레드 생성
Thread stopWatch = new Thread(new StopWatch());
// 스톱워치 실행
stopWatch.start();
// 엔터 입력 시까지 무한 대기
Scanner sc = new Scanner(System.in);
sc.nextLine();
// StopWatch 스레드 멈추게 하기
stopWatch.interrupt();
}
}
/*-----------------------------------------------------------------*/
public class StopWatch implements Runnable{
@Override
public void run() {
int count = 0;
int min = 0; // 분
int sec = 0; // 초
while(!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(10); // 1/100초
count++; // 0.01초마다 카운트 증가
if(count == 100) { // 1초가 됐을 때
sec++;
count = 0;
}
if(sec == 60) { // 1분이 됐을 때
min++;
sec = 0;
}
for(int i=0; i<30; i++) System.out.println();
System.out.printf("%02d분 %02d초 %02d \n",min,sec,count);
} catch (InterruptedException e) {
System.out.println("=== 종료 ===");
Thread.currentThread().interrupt(); // false -> true
// 현재 StopWatch 스레드에서 interrupt() 호출
}
}
}
}
'Java > 기본 개념' 카테고리의 다른 글
변수(Variable) (0) | 2024.12.16 |
---|---|
프로그래밍 기초 (0) | 2024.12.16 |
컬렉션(Collection) (2) | 2024.11.17 |
네트워크(Network) (1) | 2024.11.17 |
입출력 (IO_Input / Output) (3) | 2024.11.17 |