[Java] 자바에서 Thread 만들기

rara_kim·2022년 8월 11일
0

Java

목록 보기
21/39
post-thumbnail

Thread란?

  • Process: 실행 중인 프로그램. 프로그램이 실행되면 OS로 부터 메모리를 할당받아 프로세스 상태가 됨.
  • Thread: 하나의 프로세스는 하나 이상의 Thread를 가지게 되고, 실제 작업을 수행하는 단위는 Thread이다.


Multi-Threading

  • 여러 Thread가 동시에 수행되는 프로그래밍, 여러 작업이 동시에 실행되는 효과.
  • Thread는 각각 자신만의 작업 공간을 가진다. context
  • 각 Thread 사이에서 공유하는 자원이 있을 수 있다. 자바에서는 static instance
  • 여서 Thread가 자원을 공유하여 작업이 수행되는 경우 서로 자원을 차지 하려는 race condition이 발생할 수 있다.
  • 이렇게 여러 Thread가 공유하는 자원 중 경쟁이 발생하는 부분을 critical section이라고 한다.
  • critical section에 대한 동기화를 구현하지 않으면 오류가 발생할 수 있다.


Thread 구현하기

Thread 클래스를 상속하여 만들기

class MyThread extends Thread{
	public void run() {
		int i;
		for(i = 0; i<200; i++) {
			System.out.print(i + "\t");
		}
	}
}

public class ThreadTest {
	public static void main(String[] args) {
		System.out.println(Thread.currentThread());    //현재 실행중인 Thread 확인
		MyThread th1 = new MyThread();
		th1.start();
		
		MyThread th2 = new MyThread();
		th2.start();
	}
}

Runnable 인터페이스를 구현하여 만들기

  • 자바는 다중 상속이 허용되지 않으므로 이미 다른 클래스를 상속한 경우 Thread를 만들기 위해 Runnable 인터페이스를 구현하도록 한다.
class MyThread2 implements Runnable{
	public void run(){
		int i;
		for(i=0; i<200; i++){
			System.out.print(i + "\t");	
		}
	}
}


public class ThreadTest2 {
	public static void main(String[] args) {
		System.out.println("main start");
		
		MyThread2 mth = new MyThread2();
		Thread th1 = new Thread(mth);
		th1.start();
		
		Thread th2 = new Thread(new MyThread2());
		th2.start();
		
		System.out.println("main end");
	}
}

Thread Status

start가 불리면 Thread가 Runnable상태가 되고 CPU를 점유할 수 있는 상태가 된다.
그리고 Thread가 실행이 되고 끝나면 Dead상태가 된다.

Not Runnable은 절대 CPU를 점유할 수 없는 상태를 뜻하는데, Not Runnable 상태가 지속되면 이른바 좀비가 되어버린다.

  • sleep(시간): 지정한 시간(단위: millisecond)만큼 Thread를 쉬게 만든다. 지정한 시간이 지나면 Thread가 다시 Runnable 한 상태가 된다.
  • wait(): 한정된 리소스 중 유효한 리소스가 생길 때까지 기다리게 한다.
  • notify(): 리소스가 유효한 상태가 되면 프로그램에서 Notify()를 실행해 Not Runnable 상태인 Thread 중 하나가 깨어난다.
  • notifyAll(): wati()에 의해 Not Runnable 상태가 된 Thread를 전부 깨운다.
  • join(): ThreadA와 ThreadB가 동시에 실행될 때, B의 결과를 A가 참조해야하는 경우가 있다. 그런 경우 join()을 이용한다. A가 join()을 사용하면 A는 Not Runnable 상태가 되고, B의 실행이 완료된 후 A는 Runnable 상태가 된다.


Thread 클래스의 메서드

Thread 우선순위

  • Thread.MIN_PRIORITY(=1) ~ Thread.MAX_PRIORITY(=10)
  • 디폴트 우선순위 : Thread.NORMAL_PRIORITY(=5)
  • 우선 순위가 높은 Thread가 CPU의 배분을 받을 확률이 높다.
  • setPriority() / getPriority()
class PriorityThread extends Thread{
	public void run(){
		int sum = 0;
        
		Thread t = Thread.currentThread();
		System.out.println( t + "start");
	
		for(int i =0; i<=1000000; i++){	
			sum += i;
		}
		System.out.println( t.getPriority() + "end");
	}
}


public class PriorityTest {
	public static void main(String[] args) {
		int i;
		for(i=Thread.MIN_PRIORITY; i<= Thread.MAX_PRIORITY; i++){
			PriorityThread pt = new PriorityThread();
			pt.setPriority(i);
			pt.start();
		}
	}
}

Join

  • 동시에 두 개 이상의 Thread가 실행 될 때 다른 Thread의 결과를 참조하여 실행해야 하는 경우 사용
  • join() 함수를 호출한 Thread가 Not Runnable상태가 된다.
  • 다른 Thread의 수행이 끝나면 Runnable상태로 돌아온다.
public class JoinTest extends Thread{
	int start;
	int end;
	int total;
	
	public JoinTest(int start, int end){
		this.start = start;
		this.end = end;
	}
	
	public void run(){
		int i;
		for(i = start; i <= end; i++){
			total += i;
		}
	}
	
    
	public static void main(String[] args) {
		JoinTest jt1 = new JoinTest(1, 50);
		JoinTest jt2 = new JoinTest(51, 100);
			
		jt1.start();
		jt2.start();
		
		try{
			jt1.join();         //join() 함수를 사용하지 않는 경우
			jt2.join();         //Thread 실행 결과값이 기대값과 달라진다.
			
		}catch (InterruptedException e) {
			System.out.println(e);
		}
		
		int lastTotal = jt1.total + jt2.total;
		
		System.out.println("jt1.total = " + jt1.total);
		System.out.println("jt2.total = " + jt2.total);
		
		System.out.println("lastTotal = " + lastTotal);	
	}
}

Interrupt()

  • 다른 Thread에 예외를 발생시키는 interrupt를 보낸다.
  • Thread가 join(), sleep(), wait() 함수에 의해 Not Runnable 상태일 때 interrupt() 메서드를 호출하면 다시 runnable 상태가 될 수 있다.

Thread 종료하기

  • 무한 반복의 경우 while(flag)의 flag 변수값을 true로 바꾸어 종료 시킨다.

💡Thread 종료하기 예제
‘A’ 를 입력 받으면 첫 번째 thread를
‘B’ 를 입력 받으면 두 번째 thread를
‘C’ 를 입력 받으면 세 번째 thread를
‘M’을 입력 받으면 모든 thread와 main() 함수를 종료한다.

public class TerminateThread extends Thread{
	private boolean flag = false;
	int i;
	
	public TerminateThread(String name){
		super(name);
	}
	
	public void run(){
		while(!flag){
			try {
				sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println( getName() + " end" );
	}
	
	public void setFlag(boolean flag){
		this.flag = flag;
	}
	
	
    
	public static void main(String[] args) throws IOException {
		TerminateThread threadA = new TerminateThread("A");
		TerminateThread threadB = new TerminateThread("B");
		TerminateThread threadC = new TerminateThread("C");
		
		threadA.start();
		threadB.start();
		threadC.start();
		
		int in;
		while(true){
			in = System.in.read();
			if ( in == 'A'){
				threadA.setFlag(true);
			}else if(in == 'B'){
				threadB.setFlag(true);
			}else if( in == 'C'){
				threadC.setFlag(true);
			}else if( in == 'M'){
				threadA.setFlag(true);
				threadB.setFlag(true);
				threadC.setFlag(true);
				break;
			}
		}
		System.out.println("main end");
	}
}
profile
느리더라도 꾸준하게

0개의 댓글