자바 문법 - 5주차(쓰레드)
프로세스: 실행중인 프로그램을 의미. os에서 프로세스에게 code, data, memory 할당
쓰레드: 프로세스 내에서 일하는 코드 실행의 흐름(일꾼). 프로세스에 프로그램 실행 요청이 들어오면 쓰레드가 일을 처리함. 명령 실행을 위한 stack, heap 영역 존재.
자바에서 메인 쓰레드가 자신 외의 작업 쓰레드들을 생성해서 병렬로 코드 실행. 여러 작업을 동시에 할 수 있어서 성능이 좋아지고 자원의 효율적인 사용이 가능하지만, 프로세스의 자원을 공유하면서 작업하기 때문에 자원을 서로 사용하려고 하는 충돌이 발생할 수 있음
자바에서 main()메소드만 실행시키는 경우 싱글쓰레드.=> main(): 메인쓰레드가 됨
자바에서 쓰레드를 구현하는 방법은 1. Thread 상속 2. Runnable 인터페이스 사용 3. 람다식 사용
public class Main {
public static void main(String[] args) {
TestThread thread = new TestThread(); //쓰레드 생성
thread.start(); //쓰레드 실행
}
}
//쓰레드 구현
class TestThread extends Thread {
@Override
public void run() {
for (int i = 0; i <100; i++) {
System.out.print("*");
}
}
}
1. 자바에서 제공하는 Thread 클래스 상속받아서 run 메소드 오버라이딩을 통해 쓰레드 구현
public class Main {
public static void main(String[] args) {
Runnable run = new TestRunnable();
Thread thread = new Thread(run);
thread.start();
}
}
class TestRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i <100; i++) {
System.out.print("$");
}
}
}
2. 자바에서 제공하는 Runnable 인터페이스 사용해서 run 메소드 오버라이딩을 통해 쓰레드 구현
인터페이스는 다른 클래스를 상속받을 수 있지만 thread를 상속받으면 다른 클래스 상속을 못하기 때문에 확장성을 위해 Runnable 인터페이스를 주로 사용함.
public class Main {
public static void main(String[] args) {
Runnable task = () -> {
for (int i = 0; i < 100; i++) {
System.out.print("$");
}
};
Runnable task2 = () -> {
for (int i = 0; i < 100; i++) {
System.out.print("*");
}
};
Thread thread1 = new Thread(task);
thread1.setName("thread1");
Thread thread2 = new Thread(task2);
thread2.setName("thread2");
thread1.start();
thread2.start();
}
}
3. Runnable 람다식을 사용. 클래스를 따로 작성할 필요없이 빠르게 작성 가능
-> 위 코드는 쓰레드가 2개이기 때문에 멀티쓰레드이며 위 코드를 실행하면 순서가 정해져있지 않아 $와 *가 일정하지 않게 출력됨. 두 쓰레드가 번갈아서 실행되어서 실행 순서를 알 수 없음
데몬 쓰레드: 보이지 않는 곳에서 실행되는 낮은 우선순위를 가진 쓰레드. 그래서 좀 늦게 실행됨.
public class Main {
public static void main(String[] args) {
Runnable demon = () -> {
for (int i = 0; i < 1000000; i++) {
System.out.println("demon");
}
};
Thread thread = new Thread(demon);
thread.setDaemon(true); // true로 설정시 데몬스레드로 실행됨
thread.start();
for (int i = 0; i < 100; i++) {
System.out.println("task");
}
}
}
setDaemon(true)로 설정시 데몬스레드로 실행됨.
-> 위 코드는 demon이 먼저 실행되고 task가 출력되도록 했지만 task가 99까지 모두 출력되면 demon은 작업이 끝나기 전이어도 같이 끝남
사용자 쓰레드: 높은 우선순위를 가진 쓰레드. 메인 쓰레드가 사용자 쓰레드에 속하고 위에서 작성한 데몬 쓰레드를 제외한 모든 쓰레드가 사용자 쓰레드.
setPriority()로 쓰레드 우선순위 설정 가능. getPriority()로 우선순위 반환해서 확인 가능. 1-10 사이 숫자로 나타내는데 높을수록 우선순위가 높음
쓰레드 그룹: 모든 쓰레드는 무조건 하나의 그룹에 포함되어 있어야 한다. 그룹을 미리 지정하지 않으면 main 쓰레드에 속하게 됨
// ThreadGroup 클래스로 객체를 만듭니다.
ThreadGroup group1 = new ThreadGroup("Group1");
// Thread 객체 생성시 첫번째 매개변수로 넣어줍니다.
// Thread(ThreadGroup group, Runnable target, String name)
Thread thread1 = new Thread(group1, task, "Thread 1");
Thread thread2 = new Thread(group1, task, "Thread 2");
// interrupt()는 일시정지 상태인 쓰레드를 실행대기 상태로 만듭니다.
group1.interrupt();