Thread in Java
자바에서 Thread를 구현하는 방법은 2가지가 있다
1.Runnable interface
구현
2.Thread
클래스 상속
Runnable
인터페이스를 구현하는 경우에는 해당 클래스를 인스턴스화해서 Thread 생성자
에 argument로 넘겨주어야 함run()
을 호출하면 Runnable
인터페이스에서 구현한 run()
이 호출되므로 따로 오버라이딩 하지 않아도 되는 장점이 있음public class ConsumerRunnable implements Runnable{
int num;
public ConsumerRunnable(int num) {
this.num=num;
}
@Override
public void run () {
System.out.println("#"+num+" start");
for (int i=0; i<1000; i++) {
System.out.println("#"+num+" : "+i);
}
System.out.println("#"+num+" end");
}
}
=> Thread c3=new Thread(new ConsumerRunnable(3));
c3.start();
Thread
클래스를 상속받은 경우는, 상속받은 클래스 자체를 스레드로 사용할 수 있음Thread
클래스를 상속받으면 스레드 클래스의 메소드 (getName())
을 바로 사용할 수 있지만, Runnable
구현의 경우 Thread
클래스의 static 메소드인 currentThread()
를 호출하여 현재 스레드에 대한 참조를 얻어와야만 호출이 가능<currentThread ().getName() 사용>
public class ThreadTest implements Runnable {
public ThreadTest() {}
public ThreadTest(String name){
Thread t = new Thread(this, name);
t.start();
}
@Override
public void run() {
for(int i = 0; i <= 50; i++) {
System.out.print(i + ":" + Thread.currentThread().getName() + " ");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Thread 구현
public class ConsumerThread extends Thread{
int num;
public ConsumerThread(int num) {
this.num=num;
}
@Override =====> run을 override
public void run () {
System.out.println("#"+num+" start");
for (int i=0; i<1000; i++) {
System.out.println("#"+num+" : "+i);
}
System.out.println("#"+num+" end");
}
}
스레드 실행
스레드 실행은
run()
이 아닌start()
로 호출
call stack
-> 실질적인 명령어들을 담고 있는 메모리로 하나씩 거내서 실행시키는 역할 (만약 동시에 두 가지 작업을 한다면, 두 개 이상의 콜 스택이 필요함)run()
메소드를 이용한다는 것은 main()의 콜스택 하나만을 이용하는 것으로 스레드의 활용이 아님 -> start()
메소드를 호출하여 JVM이 스레드를 위한 콜스택을 새로 만들고, context switching
동작동기화
여러 스레드가 같은 프로세스 내의 자원을 공유하면서 작업할 때 서로의 작업이 다른 작업에 영향을 주기 때문에 동기화 필수적
synchronized
키워드로 임계영역을 설정public synchronized void saveMoney(int save){ // 입금
int m = money;
try{
Thread.sleep(2000); // 지연시간 2초
} catch (Exception e){
}
money = m + save;
System.out.println("입금 처리");
}
public synchronized void minusMoney(int minus){ // 출금
int m = money;
try{
Thread.sleep(3000); // 지연시간 3초
} catch (Exception e){
}
money = m - minus;
System.out.println("출금 완료");
}
Sleep사용 -> Running 상태에서 Runnable 상태로
Synchronized
블록 내에서 실행이 되어야 함wait ()
: 스레드가 lock을 가지고 있으면 lock 권한을 반납하고 대기하게 만듦notify ()
: 대기 상태인 스레드에게 다시 lock 권한을 부여하고 수행하게 만듦notifyAll ()
: 잠들어있던 스레드 모두를 깨움Reference
https://gyoogle.dev/blog/computer-language/Java/Thread.html