JAVA

[JAVA] Thread 스레드

sian han 2022. 4. 14. 20:41

※ 스레드 

  - 프로세스에서 작업을 처리하는 일꾼 / 별도의 실행 흐름

  - 모든 프로세스에는 최소한 하나 이상의 쓰레드가 존재함

  - 한 번 사용한 쓰레드는 다시 재사용할 수 없다

 

 

Thread 를 구현하는 두가지 방법 (면접질문으로 나왔었음) 

 

1. Thread 클래스를 상속받는 방법

   - Thread 클래스의 run()을 오버라이딩해서 작업한다

class MyThread1 extends Thread {
	public void run() {
		for (int i =0;i<5;i++) {
			System.out.println(getName()); //스레드의 이름을 가져와서 5번찍어라
		}
	}
}

 - Thread 클래스를 상속받으면, Thread 클래스의 메서드를 직접 호출 할 수 있다 =>getName()

                                             ㄴ Thread currentThread() - 현재 실행중인 쓰레드의 참조를 반환

                                                 String getName() - 쓰레드의 이름을 반환

 

 

 

 

2. Runnable 인터페이스를 구현하는 방법

  - Runnable 인터페이스에는 run() 메서드 하나만 존재한다. 이 run 메서드를 implements 해서 작업

class MyRunnable1 implements Runnable{ 
	
	@Override
	public void run() { 
		for(int i =0;i<5;i++) {
			System.out.println(Thread.currentThread().getName());
		}
	}
	
}

 - Runnable을 구현하면 Thread 클래스의 static 메서드인 currentThread() 를 호출하여

   쓰레드에 대한 참조를 얻어 와야만 Thread 클래스의 메서드 호출 가능하다

 

 

 

Thread 실행하기

 

Thread 실행과정 : 

1. main 메서드에서 쓰레드의 start 메서드를 호출한다
2. start 메서드는 쓰레드가 작업을 수행하는데 사용될 새로운 호출스택을 생성한다
3. 생성된 호출스택에 run 메서드를 호출해서 쓰레드가 작업을 수행하도록 한다
4. 이제는 호출스택이 2개이기 때문에 스케줄러가 정한 순서에 의해서 번갈아 가면서
실행된다

 

 

1. Thread 상속받아서 구현한 것 실행

MyThread1 th1 = new MyThread1("나의 쓰레드1"); //쓰레드 객체생성
th1.start(); // 실행

 - 반드시 객체생성 후 start() 메서드를 사용해야 실행된다.

 

 

 

2. Runnable 인터페이스로 구현한 것 실행

  - Runnable 인터페이스를 구현한 클래스의 인스턴스를 생성한 다음,

   이 인스턴스를 가지고 Thread 클래스의 인스턴스를 생성할 때 생성자의 매개변수로 제공해야 함

   ( = Runnable 은 쓰레드 객체생성 후 참조변수를 쓰레드의 생성자에 넣어야 실행가능하다

MyThread r = new MyThread();
Thread t = new Thread(r); //Thread의 생성자 : Thread(Runnable target) 
t.start();

 

 

 

 

 

Thread의 메서드

 

▷ Thread 이름 지정 / 변경

  - Thread 생성자 사용

  - Thread 의 setName() 사용

Thread(Runnable target, String name)
Thread(String name)
void setName(String name)

  - 쓰레드의 이름을 지정하지 않으면 'Thread-번호' 의 형식 으로 이름이 정해짐

 

 

start()

  - 작업시작 메서드

  - 한 번 사용한 쓰레드는 다시 재사용할 수 없기때문에 하나의 쓰레드에서 start() 는 한번만 호출될 수 있다

      ㄴ 두번이상 호출 시 : IllegalThreadStateException

  - 메모리 공간 할당 등 스레드의 실행을 위한 기반을 마련해준 후

    대신 run() 을 호출해준다

            ㄴ run이 호출되면 쓰레드는 자신만의 메모리 공간을 할당 받아서 별도의 실행흐름을 형성함

 

 

 join()

  - 지정된 시간동안 스레드가 실행되도록 한다 지정된 시간이 지나거나 작업이 종료되면
     join()을 호출한 스레드로 다시 돌아와 실행을 계속한다

 

 

 

sleep(int 밀리초)

 - 1밀리초 = 0.001초 / 1000밀리초 = 1초

Thread.sleep(1000); // 1초동안 쓰레드를 재움(일시정지시킴)

 

예제 ) 10초내에 값을 입력하지 않으면 프로그램종료

public class ThreadTest4 {
	static boolean inputCheck=false; //입력하면 true 가됨
	
	public static void main(String[] args) {
		MyThread3 th = new MyThread3();
		th.start();
		
		MyRunnable2 r = new MyRunnable2();
		Thread th2 = new Thread(r);
		th2.start();
		
		System.out.println("main쓰레드 종료!");
	}

}
//값을 입력하면 inputcheck 변수를 true 로 만들어주는 Thread
//runnable 사용
class MyRunnable2 implements Runnable{

	@Override
	public void run() {
		System.out.println("10초안에 값을 입력해야 합니다.");
		String str=JOptionPane.showInputDialog("값 입력!");
		ThreadTest4.inputCheck=true; //입력되면  true로 바꿔 ! 
		
		System.out.println("입력한 값은 " + str);
	}	
}

//count를 해주고, 값이 입력되지 않으면 자동종료해주는 Thread
//thread 상속
class MyThread3 extends Thread{
	public void run() {
		for(int i=10;i>0;i--) {
			if(ThreadTest4.inputCheck) return; //만약 true 면 return 빠져라 ! 
			
			System.out.println(i); //false면 for 만큼 돌려 ! 
			
			try {
				sleep(1000);  //지정된 시간동안 쓰레드를 일시정지시킴
			} catch (InterruptedException e) {
				e.printStackTrace();
			} 
		}//for
		
		System.out.println("10초 동안 값이 입력되지 않아 종료함!");
		System.exit(0); //프로그램 완전종료 . 
		                //return은 프로그램의 메서드만 탈출시킨다. 따라서 exit 를 써줘야 프로그램종료이다.
	}
}

 

 

 

 Thread의 메모리 구성

 

쓰레드가 생성되면 가상머신은 쓰레드의 실행을 위한 별도의 메모리 공간을 할당한다.

 => 모든 쓰레드는 자신의 스택을 할당 받는다. 그러나 힙과 메소드 영역은 모든 쓰레드가 공유한다

 

A 쓰레드가 만든 인스턴스(=객체)의 주소값(=참조변수) 만 알면

B 쓰레드도 A 쓰레드가 만든 인스턴스에 접근 가능하다

 

▽ 이게 무슨말이냐며언 ~! 

Runnable로 implements 해서 Thread 를 생성하고, 로컬변수를 선언한다

main 에서 Thread 인스턴스를 2개 생성하고 같은 주소값을 넣어주면

두 Thread는 로컬변수 insVar을 공유하게 된다

 

 

 

▶ 싱글 쓰레드 : 실행 흐름(쓰레드)이 하나밖에 없으므로 한 번에 하 나의 작업밖에 하지 못함

 

 멀티 쓰레드 : 하나의 응용 프로그램이 두 개의 작업을 병렬적으로 처리하는 것이 가능

   - CPU 이외의 자원을 사용하는 경우에 싱글쓰레드 프로세스보다 멀티쓰레드 프로세스가 더 효율적

 

 

▶ Thread의 우선순위

  - 둘 이상의 쓰레드가 생성될 수 있기 때문에 자바 가상 머신은 쓰레드의 실행을 스케줄링(컨트롤)해야 함

  - 가장 높은 우선순위 : 10 

  - 가장 낮은 우선 순위 :1

int getPriority() : 쓰레드의 우선순위를 반환
void setPriority(int newPriority) :쓰레드의 우선순위를 지정한 값으로 변경
MyThread4 th1 = new MyThread4();
		MyRunnable3 r = new MyRunnable3();
		Thread th2 = new Thread(r);
		
		th2.setPriority(10);
		th1.setPriority(1);
		
		System.out.println("th1 우선순위(-) : " + th1.getPriority());
		System.out.println("th2 우선순위(2) : " + th2.getPriority());

 

 

▶ 데몬 쓰레드 (daemon thread)

  - 쓰레드 3개가 동시에 작업하고있을 때 , main 쓰레드가 종료되었다고 다른 쓰레드들도 함께 종료되는 건 아니다.

  - 데몬쓰레드를 사용하면 일반 쓰레드가 모두 종료되면 데몬 쓰레드는 강제적으로 자동 종료된다

  - setDaemon(boolean on)은 반드시 start()를 호출하기 전에 실행되어야 한다

    그렇지 않으면 IllegalThreadStateException이 발생한다

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

'JAVA' 카테고리의 다른 글

[JAVA] 이것이 자바다 !_6장 클래스  (0) 2023.11.29
[JAVA] 네트워킹 NetWorking  (0) 2022.04.17
[JAVA] IO  (0) 2022.04.13
[JAVA] GUI / 계속 추가예정  (0) 2022.04.11
[JAVA] AWT.EVENT  (0) 2022.04.06