프로세스(process) - OS에서 실행중인 하나의 애플리케이션을 프로세스라 칭한다

스레드(thread) - 1가지 작업을 실행하기 위하여 순차적으로 실행할 코드를 실처럼 이어놓았다는 의미로 1개의 스레드는 1개의 코드 실행흐름이기에 1개의 프로세스 내에서 스레드가 2개면 2개의 코드실행 흐름이 생긴다는 의미이다.

 

21개의 프로세스..

1개의 프로세스가 2개의 스레드를 실행하는것을 멀티스레드라 칭하는데 이러한 작업작업을 위해선 OS가 CPU 및 메모리 자원을 프로세스마다 할당해주는 작업을 한다.

 

위의 사진과 연관지어 설명하자면

1. 1개의 프로세스는 여러개의 프로세스를 가질수 있다 (사진속 크롬은 21개의 프로세스를 갖고있으며 새로운창 1개만 추가해도 프로세스가 여러개 추가되는걸 볼수있다.) 

2. 각 프로세스마다 싱글스레드 및 멀티스레드가 실행될수 있다는 의미이다.

 

추가로 이전에 예외와 에러에 대한 포스팅을 진행했는데 부연설명을 하면 예외는 문제생겨도 실행, 에러는 발생시 일단 종료 하는걸 하였다.이것은 웹페이지가 응답없음이 발생했을때 에러로 크롬의 전체 프로세스가 꺼지는것으로 확인이 가능하다.


스레드의 우선순위

멀티스레드는 동시성 또는 병렬성으로 실행되는데스레드의 갯수가 코어의 숫자보다 많을경우 스레드는 어떤순서에 의하여 동시성으로 실행할지를 결정하는데 이것을 스레드스케쥴링이라 칭한다.

 

스레드 스케쥴링 - 스레드 개수가 코어수보다 많을때 스레드를 어떤순서로 동시성으로 실행할지 결정하는것

동시성 - 멀티작업이 1개의 코어에서 멀티스레드가 번갈아가며 실행하는 성질

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

 

스레드 스케쥴링은 우선순위방식, 순환할당방식 2가지로 나뉜다.

우선순위방식(Priority) -> 중요도가 높은스레드가 더 많은 스레드를 실행하는것으로 스레드는 1~10의 우선순위를 가지며 디폴트로 5의 우선순위를 할당받는데 우선순위를 변경하려면 하단의 양식처럼 사용하면 된다. 

//thread.setPriority(우선순위);
thread.setPriority(Thread.MAX_PRIORItY);	//중요도 10
thread.setPriority(Thread.NORM_PRIORItY);	//중요도 5
thread.setPriority(Thread.MIN_PRIORItY);	//중요도 1
thread.setPriority(4);				//중요도 4
thread.setPriority(1);				//중요도 1

 

순환할당방식(Round-Robin) -> 일정시간(Time Slice)마다 번갈아가며 실행하는것이며 해당방식은 JVM에 의하여 정해지기에 코드로 제어는 불가능하다

(JVM - 자바가상머신)


메인 스레드

main스레드의 첫 코드부터 아래로 순차적으로 실행하며 코드 중간에 외부에 있는 스레드가 있을경우 그것을 중간에 실행한뒤 메인스레드로 넘어오는 방식이다.

요점은 싱글 스레드에선 메인스레드 종료시 프로세스가 종료되지만 멀티스레드 종료시 실행중인 스레드가 1개라도 있다면 프로세스는 종료되지 않는다. -> 기타 프로그램이 실행중일때 종료하려면 이 프로그램과 관련된 프로세스를 종료해야 가능하다 (백신 삭제할때 자주 나온다)

 

public static void main(String[] args){
		//메인스레드는 요기서 main()을 뜻한다
}

작업 스레드 

스레드를 구현하는 방식에는 2가지 방식있다.

1. Thread클래스로부터 직접생성

2. Theard를 상속받아 하위클래스 생성

 

스레드 클래스로부터 직접생성

먼저 스레드를 직접 생성했을때 스레드는 Thread-n이라는 형태의 이름으로 저장되며 이를 변경하려면 Thread.currentThread()메서드를 우선 선언해야하고 setName, getName 활용해 이름을 변경할수 있다.

//이름확인, 수정을 위한 선행코드
Thread thread = Thread.currentThread();

//이름변경
thread.setName("스레드 이름");

//이름확인(호출)
thread.getName();

 

하단의 코드는 터치했을때 소리와 동시에 텍스트를 출력하는 코드를 만들었지만 실행시 (A)가 전부 실행된뒤 (B)가 실행되는 순서로 예상과 다른 결과가 나타났다 (위에 말한 쓰레드는 한번에 1줄의 코드씩 실행하기에 (A)가 전부 실행되야 (B)가 실행되기 때문)

//양식 Thread a = new Thread (Runnable target);

public class BeepPrintEx1{
	public static void main(String[] args) {
    	Toolkit toolkit = Toolkit.getDefaultToolkit;
    	for (int i=0; i<5; i++) {
        	toolkit.beep();		//1초마다 소리 출력 (A)
            try{ Thread.sleep(1000); } catch (Exception e) {}
        }
        
    	for (int i=0; i<5; i++) {		//1초마다 텍스트 출력 (B)
        	System.out.println("띵")
            try { Thread.sleep(1000); } catch(Exception e) {}
        }
    }
}

이를 해결하기 위해선 싱글쓰레드가 아닌 멀티쓰레드로 코드변경이 필요하고 이를 하단의 코드와 같이 작성한다면 문제없이 소리와 텍스트가 동시에 출력됨을 확인할수 있다.

(A) 코드 - 1초마다 사운드 출력

//소리출력 스레드 (A)
//Thread 직접생성
public class BeepThread extend Thread {
	@Override
    public void run() {
    Toolkit toolkit = Toolkit.getDefaultToolkit;
    	for (int i=0; i<5; i++) {
        	toolkit.beep();		//1초마다 소리 출력 (A)
            try{ Thread.sleep(1000); } catch (Exception e) {}
        }
    }


}

 

(B) 코드 - 1초마다 사운드 및 텍스트 출력 ((A)코드를 객체화하여 동시실행)

public class BeepPrintEx2 {
    public static void main (String[] args) {
	Thread thread = new BeepThread();	//(A)코드 객체화
	thread.start();				//(A)코드 실행
    
	for (int i=0; i<5; i++) {		//1초마다 텍스트 출력 (B)
            System.out.println("띵")
            try { Thread.sleep(1000); }
                catch(Exception e) {}
        }
    }
}

 

Theard를 상속받아 하위클래스 생성

1

 

스레드의 우선순위는 

 

동기화메서드(synchronized)

OS에서 실행중인 하나의 애플리케이션을 프로세스라 칭하고 멀티스레드는 1개의 프로세스가 여러개의 스레드를 갖는것이라 배웠다

멀티스레드로 작업할경우 여러 작업을 동시에 할수 있지만 여기에도 단점이 한가지 존재한다.

그것은 바로 객체를 공유해서 사용하는 경우이다.

 

객체의 공유

멀티스레드를 사용하는 프로그램은 스레드들이 객체를 공유해서 작업해야하는 경우가 있는데 같은객체를 공유하게되면 스레드A를 사용하던 객체가 스레드B에 의하여 다른결과가 나올수도 있다.

한가지 예시를 들자면 계산기 1개로 2명이 돌려쓰는경우가 있는데 내가 계산한 이전값(A)이 다른사람이(B) 써서 변경되는 사례로 이를 하단에 코드로 구현하였다..

// 메인코드
public class test1 {
	public static void main(String[] args) {
    	Calculator calculator = new Calculator();
    	
        User1 user1 = new User1();	//User1 스레드 생성
    	user1.setCalculator(calculator);	//공유객체 설정
        user1.start();			//User1 스레드 시작
        
        User2 user2 = new User2();	//User2 스레드 생성
    	user2.setCalculator(calculator);	//공유객체 설정
        user2.start();		//User2 스레드 시작     
    }
}

(A),(B) 코드 -> 이름, 저장값만 다름 

 

public class User1 extends Thread {	//(A)
	private Calculator calculator;
	
    public void setCalculator(Calculator calculator) {
	this.setName("User1");
    this.calculator = calculator;
	}
    
    public void run() {
    calculator.setMemory(100)	//메모리에 100 저장
    }
    
################################

public class User2 extends Thread { //(B)
	private Calculator calculator;
	
    public void setCalculator(Calculator calculator) {
	this.setName("User2");
    this.calculator = calculator;
	}
    
    public void run() {
    calculator.setMemory(50)	//메모리에 50 저장
    }

공유객체코드

//계산용 코드
public class Calculator{
	private int memory;
    
    public int getMemory() {	//메모리 값 반환용
    	return memory;
    }
	
    public void setMemory(int Memory) {	//초기 메서드
  //public synchronized void setMemory(int Memory) { //동기화 메서드 synchronized추가
    	this.memory = memory;
    	try{
            Thread.sleep(2000);
        } catch(InterrupedException e) {}
        System.out.println(Thread.currentThread().getName() + ": " + this.memory);
    	//Thread.currentThread().getName()는 스레드 이름이다.
    }
}

 

현재 Calculator의 setMemory를 본다면 User1이 진행되고 User2가 진행되지만 User2가 User1과 같은객체를 참조하기에 User1과 User2는 같은결과가 나오는것을 확인할수 있다.

이러한 문제를 방지하기 위한게 동기화 메서드(synchronized)이다.

상단의 코드를 그림으로 표현하면 다음과 같다.

 

현재 코드가 어떤방식으로 진행되는지 나오는데 Calculator가 동일한 객체를 참조해서 사용하기 떄문에 User1도, User2도 50이 나타나는것이다. 

 

이것을 현재 주석처리된 synchronized를 추가한다면 다음과 같은 그림이 된다.

Calculator에 synchronized를 추가하여 User1이 실행되는동안 User2가 실행되지 않도록 만든것이다,

 

 

 

요점정리

1. 프로세스(process) - OS에서 실행중인 하나의 애플리케이션 // 스레드(thread) - 1가지 작업을 실행하기 위하여 순차적으로 실행할 코드

2. 싱글 스레드에선 메인스레드 종료시 프로세스가 종료 / 멀티스레드 종료시 실행중인 스레드가 1개라도 있다면 프로세스는 종료되지 않는다. (백신을 끄려면 현재 켜져있는 익스플로러를 전부 닫아라)

3. 스레드의 우선순위를 정하는것을 스레드 스케쥴링이라 하며 우선순위방식 (1~10, 디폴트5) / 순환할당방식 (인터벌로 실행되며 우선순위는 JVM이 임의로 배정) 2가지이다.

4. 작업스레드를 구현하는 방식은 클래스를 직접생성, 쓰레드를 상속받아 하위클래스로 생성한다

5. synchronized는 객체를 동기화 시키는 기능으로 멀티스레드의 공유객체간 참조를 막아 비정상적인 출력을 막는것이 목적이다.

'JAVA' 카테고리의 다른 글

DocumentBuilderFactory와 예제  (0) 2024.02.18
스레드풀  (0) 2023.03.07
동일성(identity)과 동등성(equality)  (0) 2023.02.26
예외에 관하여  (0) 2023.02.24
중첩클래스  (0) 2023.02.21

+ Recent posts