[JAVA] 자바 - 스레드 (Thread) 개념
by mini_min[JAVA]
자바 - 스레드 (Thread) 개념
✔️ 스레드 (Thread)
프로세스와 스레드의 관계는 포함관계이다.
프로세스는 운영체제로 부터 자원을 할당받은 작업의 단위로 실행 중인 하나의 프로그램을 의미함.
✨ 프로세스 : 리소스 + 스레드
✨ Code, Data, Heap, Stack 영역으로 이뤄지며 동시에 2개 이상의 프로그램을 동시 실행시키는 것을 멀티 태스킹이라고 한다.
💖 스레드는 프로스세 안에서 실행되는 흐름의 단위다.
프로세스가 할당 받은 자원을 이용하는 실행 단위 흐름이고, 모든 프로세스는 적어도 하나 이상의 스레드를 가진다.
프로세스는 자신만의 메모리/자원을 할당 받지만, 스레드는 다른 스레드와 메모리, 자원을 공유한다.
✨ Code, Data, Heap 영역은 공유하고 별도의 Stack 영역만 가진다.
✨ 둘 이상의 스레드를 가진 프로세스를 멀티 스레드 프로세스라고 한다.
✔️ 멀티 스레드 (Multi Thread)
장점 : 시스템 자원 소모가 줄어든다.
CPU 사용률을 향상시킨다.
프로그램 응답 시간이 단축된다.
단점 : 자원 공유를 위해 전역변수를 이용하므로 동기화 문제 발생
잘못된 변수 사용하거나 시간차로 프로그램에 오류 발생할 수 있다.
디버깅이 어렵다.. 🐛
✔️ 자바 메인 스레드 (Main Thread)
자바는 프로그램 시작시 기본적으로 main() 메소드를 진입 점으로 하는 메인 스레드가 생성된다.
추가로 사용자가 정의한 스레드를 생성하여 멀티 스레드를 구현할 수 있다.
💡 멀티 스레드 환경에서는 모든 스레드가 종료되어야 프로세스가 종료된다.
= 모두 종료되지 않으면 무한의 굴레가....
✔️ 스레드 구현 클래스 / 인터페이스
💖 Thread 클래스
: 스레드 생성 및 시작, 관리를 위한 클래스로 하위 클래스에서 run() 메소드를 재정의하여 스레드를 구현한다.
💖 Runnable 인터페이스
: 스레드에서 실행할 코드를 가지는 run() 메소드가 선언되어 있다.
✨ 자바는 단일 상속만 구현 가능하므로 스레드를 구현할 클래스가 다른 클래스를 상속 받은 경우 Runnable 인터페이스를 구현한다.
💡 Runnable 인터페이스를 implements 한 클래스는 run() 메소드 재정의하여 스레드 구현
✔️ 스레드 시작
: 스레드를 실행하기 위해 Thread() 클래스의 start() 메소드를 호출하면 스레드를 시작한다.
Thread 클래스를 상속받는 하위 클래스를 만든 경우
: 해당 하위 클래스의 객체를 생성 후 Thread() 클래스의 start() 메소드를 호출한다.
Runnable 인터페이스를 구현하여 클래스를 만든 경우
: Thread() 생성자에 Runnable 인터페이스 구현 클래스 객체를 인수로 넘겨 Thread 클래스 객체 생성하여 Thread 클래스의 start() 메소드 호출한다.
✔️ 스레드 구현 방법 - 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();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
MyThread1 t = new MyThread1();
t.start(); // 스레드 시작
//메인이 먼저 5개 정도 찍히면 아래 스레드가 1번 정도 찍히는 정도임.
// 메인이 일이 끝나면 나머지 아래 스레드가 찍힌다아아
System.out.println("main 스레드..");
try {
for(int i=1; i<=10; i++) {
System.out.println("main -> " + i);
Thread.sleep(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("main 스래드 종료....");
// 메인은 프로그램 시작점으로 종료점이 아니다.
// 메인이 종료되어도 프로그램은 종료되지 않을 수 있다.
// 프로그램 종료 시점은 모든 독립 스레드가 종료되는 시점이다.
}
💡 sleep : ms 단위로 일시정지한다.
✔️ 스레드 구현 방법 - 2
1) Runnable 인터페이스를 구현하는 클래스를 만들어 run() 메소드를 재정의한다.
2) Runnable 구현 클래스의 객체를 생성한다.
3) Thread 클래스의 객체를 생성하며, Thread 클래스의 객체를 생성할 때 생성자에 2)번의 객체를 인자로 전달한다.
4) Thread 클래스의 객체의 start() 메소드를 호출한다.
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); // 지정시간 (ms) 동안 스레드 실행이 일시 중지
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
MyThread2 obj = new MyThread2();
Thread t = new Thread(obj);
t.start();
System.out.println("main 스레드..");
try {
for(int i=1; i<=10; i++) {
System.out.println("main -> " + i);
Thread.sleep(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("main 스래드 종료....");
}
}
✔️ 스레드 구현 방법 - 3
1) 익명 클래스 이용
public static void main(String[] args) {
// 스레드 구현방법 3 : 익명 클래스
Thread t = new Thread(new Runnable() {
@Override
public void run() {
int n = 0;
try {
while(n < 20) {
n++;
System.out.println(Thread.currentThread().getName() + "-> " + n);
Thread.sleep(500); // 지정시간 (ms) 동안 스레드 실행이 일시 중지
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
});
t.start();
System.out.println("main 스레드..");
try {
for(int i=1; i<=10; i++) {
System.out.println("main -> " + i);
Thread.sleep(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("main 스래드 종료....");
}
✔️ 스레드 구현 방법 - 4
1) 람다식
public static void main(String[] args) {
// 스레드 구현 방법 4 - 람다
Thread t = new Thread( () -> {
int n = 0;
try {
while(n < 20) {
n++;
System.out.println(Thread.currentThread().getName() + "-> " + n);
Thread.sleep(500); // 지정시간 (ms) 동안 스레드 실행이 일시 중지
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
});
t.start();
System.out.println("main 스레드..");
try {
for(int i=1; i<=10; i++) {
System.out.println("main -> " + i);
Thread.sleep(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("main 스래드 종료....");
}
🔒 람다 + 스레드로 현재 시간 구하기
public static void main(String[] args) {
Thread t = new Thread(() -> {
String s;
while(true) {
Calendar cal = Calendar.getInstance();
s = String.format("%tF %tT", cal, cal);
System.out.println(s);
try {
Thread.sleep(1000);
} catch (Exception e) {
}
}
});
t.start();
System.out.println("main end...");
}
'Java' 카테고리의 다른 글
[JAVA] 자바 - TimerTask 클래스와 Timer 클래스 (0) | 2022.09.01 |
---|---|
[JAVA] 자바 - 데몬 스레드 (Daemon Thread) / 스레드 종료 (0) | 2022.09.01 |
[JAVA] 자바 - DataOutputStream / BufferedReader 버퍼 크기 주기 (0) | 2022.08.30 |
[JAVA] 자바 - RandomAccessFile / PrintWriter / BufferedWriter (0) | 2022.08.30 |
[JAVA] 자바 - 입출력 스트림 요약 (바이트 스트림 / 문자 스트림) (0) | 2022.08.30 |
블로그의 정보
개발자 미니민의 개발로그
mini_min