멀티쓰레드 프로그래밍
Thread 클래스 , Runnable 인터페이스
스레드를 작성하는 방법에는 2가지 방법이 있다.
class MyThread extends Thread{
private int count = 0;
@Override
public void run(){
System.out.println("Thread Start");
for(int i = 0; i>100; i++){
count++;
Thread.sleep(10);
}
System.out.println("Thread End and Count :" + count);
}
}
class MyRunnable implements Runnable{
private int count = 0;
@Override
public void run(){
System.out.println("Thread Start");
for(int i = 0; i>100; i++){
count++;
Thread.sleep(10);
}
System.out.println("Thread End and Count :" + count);
}
}
public class ThreadRun{
public static void main(String[] args){
Thread thread1 = new MyThread();
thread1.start();
Runnable runnable1 = new MyRunnable();
Thread thread2 = new Thread(runnable1);
thread2.start();
}
}
위 코드에서 Thread 클래스와 Runnable 인터페이스 중 어느 것이 더 좋은지는 상속의 유무를 보고 결정하면된다. Thread 클래스를 확장하는 클래스는 다른 클래스를 상속받을 수 없지만 Runnable 인터페이스는 다른 인터페이스 구현 및 클래스 상속이 가능하므로 상황에 따라 구현하면 된다.
쓰레드의 상태
![]()
스레드는 일반적으로 위와 같은 과정을 거치게 된다.
이 방식을 java에서는 어떻게 사용할까
class PrintThread extends Thread{
private Thread targetThread;
private int count = 0;
public MyThread(Thread targetThread){
this.targetThread = targetThread;
}
@Override
public void run(){
while(true){
Thread.State state = targetThread.getState(); // 스레드 상태 얻는 메소드
System.out.println("Thread State :" + state);
if(state == Thread.State.NEW){
targetThread.start();
}
if(state == Thread.State.TERMINATED){
break;
}
}
}
}
위 스레드의 상태를 찍는 클래스를 MyThread 클래스에게 적용시키면
public static void main(String[] args){
PrintState printState = new PrintState(new MyThread);
printState.start();
}
스레드의 상태가 어떤지 실시간으로 알아 볼 수 있다.
쓰레드의 우선순위
java의 우선순위는 1-10까지로 구성되어 있고 기본적으로 스레드를 생성할 시 5로 고정되어있다.
이 우선순위를 고치려면 setPriority 메소드를 사용하여 우선순위를 조정할 수 있다.
스레드의 우선순위가 올라가면 다른 스레드보다 먼저 실행할 수 있는 기회를 얻을 수 있다.
Main 쓰레드
java는 일단 시작을 한다면 하나의 쓰레드가 동작하는데 그 쓰레드를 Main 쓰레드라고 한다.
Main 쓰레드는 기본적으로 5의 우선순위를 가지며 자식 쓰레드를 생성할 떄 상속받는다.
모든 자식 쓰레드는 Main 쓰레드로부터 생성된다.
Main 쓰레드가 먼저 종료될 수도 있지만, 대체적으로 마지막으로 종료하는 편이며, 자식 쓰레드가 종료될 때 Main 쓰레드가 자식 쓰레드의 종료를 확인하지 않으면 고아 프로세스가 되므로 되도록이면 Main 쓰레드가 자식보다는 먼저 종료되지 않는것을 지향한다.

동기화
동기화란 멀티스레드 환경에서 여러 스레드가 하나의 공유자원에 접근하려 할 때 막아주는 역할을 한다.
java에서는 공유자원 동시 접근을 막기위해 synchronized 키워드를 사용한다.
synchronized 키워드는 메소드에 사용하면 해당 메소드에 락을 걸 수 있고, 메소드 내부에서 사용한다면 해당 부분에서만 락을 걸어준다.
public static void main(String[] args){
Mythread[] mythread = new Mythread[10];
for(int i = 0; i<mythread.length; i++){
mythread[i] = new Mythread();
mythread[i].start();
}
}
class MyThread extends Thread{
private int count = 0;
@Override
public void run(){
System.out.println("Thread Start");
synchronized(lock){
for(int i = 0; i>100; i++){
count++;
Thread.sleep(10);
}
}
System.out.println("Thread End and Count :" + count);
}
}
데드락
데드락이란 두 개 이상의 스레드가 자신이 점유하고 있는 자원을 가지고 있고 그 상태에서 서로의 자원을 요청하여 해당 자원의 락이 해제되기를 무한정 기다리는 상태를 말한다.
DeadLock 발생조건
- 상호 배제 (Mutual Exclusion) : 한 자원에 대해 여러 쓰레드 동시 접근 불가
- 점유와 대기 (Hold and Wait) : 자원을 가지고 있는 상태에서 다른 쓰레드가 사용하고 있는 자원 반납을 기다리는 것
- 비선점 (Non Preemptive) : 다른 쓰레드의 자원을 실행 중간에 강제로 가져올 수 없음
- 환형대기 (Circle Wait) : 각 쓰레드가 순환적으로 다음 쓰레드가 요구하는 자원을 가지고 있는 것
public class Main {
public static Object object1 = new Object();
public static Object object2 = new Object();
public static void main(String[] args) {
FirstThread thread1 = new FirstThread();
SecondThread thread2 = new SecondThread();
thread1.start();
thread2.start();
}
private static class FirstThread extends Thread{
@Override
public void run() {
synchronized (object1){
System.out.println("First Thread has object1's lock");
try {
Thread.sleep(10);
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("First Thread want to have object2's lock. so wait");
synchronized (object2){
System.out.println("First Thread has object2's lock too");
}
}
}
}
private static class SecondThread extends Thread{
@Override
public void run() {
synchronized (object2){
System.out.println("Second Thread has object2's lock");
try {
Thread.sleep(10);
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Second Thread want to have object1's lock, so wait");
synchronized (object1){
System.out.println("Second Thread has object1's lock too");
}
}
}
}
FirstThread가 자원을 점유하고 있고, SecondThread또한 자원을 점유하고 있는 상태에서 서로의 자원을 요청하는 프로그램이다.
'Java' 카테고리의 다른 글
| Java Study 6-2주차 (0) | 2023.11.11 |
|---|---|
| Java Study 6-1주차 (1) | 2023.11.11 |
| Java Study 5-1주차 (0) | 2023.11.05 |
| Java Study 4주차 (1) | 2023.10.29 |
| Java Study 3-2주차 (0) | 2023.10.14 |