WEB/JAVA

내가 보려고 정리하는 JAVA 멀티 스레드 1 - 멀티스레드 개념

멀티 프로세스애플리케이션 단위의 멀티 태스킹이라면 멀티 스레드애플리케이션 내부에서의 멀티 태스킹이라고 볼 수 있다.

 

멀티 스레드는 다양한 곳에서 사용된다.

1. 대용량 데이터의 처리 시간을 줄이기 위해 데이터를 분할해서 병렬로 처리하는 곳에서 사용

2. UI를 가지고 있는 애플리케이션에서 네트워크 통신을 하기 위해 사용

3. 다수 클라이언트의 요청을 처리하는 서버를 개발할 때


- 메인 스레드

메인 스레드가 작업 스레드보다 먼저 종료되더라도 작업 스레드가 계속 실행 중이면 프로세스는 종료되지 않는다.

 

- 작업 스레드

몇 개의 작업을 병렬로 실행할지 결정하고 각 작업별로 스레드를 생성한다.

                                                                                          (작업1)   (작업2)

(프로그램에서 병렬로 실행할 작업을 결정)  ->  메인스레드  스레드1   스레드2

Thread클래스를 직접 객체화해서 생성해도 되지만, 상속해서 하위 클래스를 만들어 생성할 수도 있다.

 

 

이제 사용하는 방법을 알아봅시다!

 

1. Thread 클래스로부터 직접 생성하는 방법

 

Thread thread = new Thread(Runnable target);

위와 같이 Runnable을 매개값으로 갖는 생성자를 호출합니다.

Runnable은 작업 스레드가 실행할 수 있는 코드를 가지고 있는 객체입니다. 인터페이스 타입이기 때문에 아래와 같이 구현 객체를 만들어 대입해야 합니다.

 

class Task implemets Runnable{
	public void run(){
    	스레드가 실행할 코드
        }
  }

run() 하나가 정의 되어 있는데. 이것을 재정의하여 실행할 코드를 작성하면 됩니다. 

하지만 작업 내용을 가지고 있는 객체이지 실체 스레드는 아닙니다. Runnable 객체를 생성 후 

 

Thread thread = new Thread(여기에)

 

위와 같이 Thread생성자로 호출해야만 비로소 작업 스레드가 생성됩니다. 아래와 같이 익명 구현 객체를 사용해도 무관합니다.

Thread thread = new Thread(new Runnable(){
	public void run(){
    	스레드가 실행할 코드
	}
});

 

Runnable 처럼 하나의 메서드를 갖고 있는 인터페이스를 함수적 인터페이스라고 하는데. 이러한 인터페이스는 람다식을 매개값으로 사용할 수 있습니다. (Java 8 이상)

Thread thread = new Thread(()->{
	스레드가 실행할 코드
} );

thread.start() 

메인스레드 -> 스레드 객체 생성 -> start() 메서드 호출 -> 작업 스레드 실행 / 메인 스레드 실행

 

2. Thread 하위 클래스로부터 생성

 

Runnable로 만들지 않고 직접 Thread의 하위 클래스로 작업 스래드를 정의할 수 있다.

아래와 같이 Thread의 run 메서드를 재정의하면 된다. 

public class Work extends Thread{
	@Override
    public void run(){
    	// 스레드가 실행할 코드
	}   
 }
 
 Thread thead = new Work();

 

아래와 같이 익명 자식 객체로 코드를 절약할 수 있다.

Thread thread = new Thread(){
    @Override
    public void run() {
        
    }
};

스레드의 이름

필수적인 역할을 하기 보다는 디버깅할 때 어떤 스레드가 어떤 작업을 하는지 확인 할 목적으로 사용된다.

메인 스레드는 "main" 이라는 이름을 가지고 있고, 직접 생상한 스레드는 자동으로 "Thread-n" 이라는 이름으로 설정된다.

변경하고 싶을 때는 

thread.setName("스레드 이름") 을 사용하면 된다. 반대로 스레드의 이름을 알고 싶을 때는

thread.getName() 을 사용하면 된다.

 

* 만약 Thread 객체를 참조하고 있지 않다면 Thread.currentThread() 를 통해 이름을 알아낼 수 있다.

public static void main(String[] arg){
	// Thraed 참조 하고 있지 않음
    Thread mainThread = Thread.currnetThread();
    mainThread.getName();
    
    // Thraed 참조 하고 있음
    ThraedA thraedA = new Thraed(){
    	@Override
        public void run(){
    		setName("TheadA");
        }
    }
    threadA.getName();
    ThreadA.start();
    
   }

 

스레드 우선순위

멀티 스레드는 동시성 or 병렬성으로 실행된다.

동시성 - 멀티 작업을 위해 하나의 코어에서 멀티 스레드가 번갈아가며 실행한다.

병렬성 - 멀티 작업을 위해 멀티 코어에서 개별 스레드를 동시에 실행한다.

 

 

싱글 코어 CPU를 이용한 멀티 스레드는 병렬적으로 실행되는 것처럼 보이지만, 사실은 번갈아가며 실행하는 동시성 작업이다.

워낙 빠르다보니 병렬적으로 보일 뿐!

 

그러므로 어떤 순서에 의해 동시성으로 시행할 것인가를 결정해야 하는데, 이것을 스레드 스케줄링이라고 한다. 

 

스레드 스케줄링은 우선순위 / 순환 할당 방식을 사용한다.

우선순위 - 우선순위가 높은 스레드가 실행 상태를 더 많이 가지도록 함 (개발자가 코드로 제어 가능) 1~10 *1이 낮은순

순환 할당 - 시간 할당량을 정해서 하나의 스레드를 정해진 시간만큼 실행하고 다시 다른 스레드를 실행 함 (가상 기계에 의해서 정해짐 코드로 제어 불가능)

 

사용법

1. thread.setPriority(1);

2. thread.setPriority(Thread.MIN_PRIORITY); -> Thread 클래스의 상수를 사용한다.