프로세스는 공장 쓰레드는 공장에서 일하는 일꾼 으로 생각하면 쉽다
모든 쓰레드는 최소한 하나 이상의 쓰레드가 존재하며 개수는 제한되어 있지 않다.
CPU의 코어 가 한번에 단 하나의 작업만 수행할 수 있으므로 실제로 동시에 처리되는 작업의 개수는 코어의 개수와 일치한다.
하나의 쓰레드를 가진 프로세스보다 두 개의 쓰레드를 가진 프로세스 가 오히려 더 낮은 성능을 보일수도 있다.
멀티쓰레드 장점
멀티쓰레드 단점
교착상태: 두 쓰레드가 자원을 점유한 상태에서 서로 상대편이 점유한 자원을 사용하려고 기다리느라 진행이 멈춰 있는 상태
Thread클래스 상속받는 방법
Runnable인터페이스를 구현하는 방법
=> Runnable인터페이스는 오로지 run()만 정의되어 있는 간단한 인터페이스다.
=> Runnable 인터페이스를 구현한 경우
Runnable 인터페이스를 구현한 클래스의 인스턴를 생성한 다음 이 인스턴스를 Thread클래스의 생성자의 매개변수로 제공 해야한다.
쓰레드 클래스를 상속 받으면 자손 클래스에서 조상 Thread클래스의 메서드를 직접 호출 할수 있다.
runnable 인터페이스는 Thread클래스의 static메서드인 currentThread() 를 호출하여 쓰레드에대한 참조를 얻고 해야한다.
start()가 호출 되었다고 바로 실행 되는것이 아니라 실행 대기 상태에 있다가 자신의 차례가 되면 실행된다.
실행이 한번 종료된 쓰레드는 다시 실행 불가 -> 새로운 쓰레드를 생성한다음 start() 호출
Start()는 새로운 쓰레드가 작업을 실행하는데 필요한 호출 스택을 생성한 다음에 run()을 호출해서 생서된 호출스택에 run()이 첫 번쨰로 올라가게 한다.
모든 쓰레드들은 독립적인 작업수행을 위해 자신만의 호출스택이 필요하다.
1 = main메서드에서 쓰레드의 start()를 호출한다
2 = start()는 새로운 쓰레드를 생성하고 쓰레드가 작업하는 공간, 사용될 호출스택 생성
3 = 새로 생성된 호출스택에 run()이 호출되어 쓰레드가 독립된 공간에서 작업 수행을 한다.
4 = 호출 스택이 2개이므로 스케줄러가 정한 순서에 의해서 번갈아 가면서 실행된다.
작업을 주어진 시간에 마치지 못한 쓰레드는 다시 자신의 차례가 돌아올 때까지 대기상태로 있게된다.
작업을 마친 쓰레드 즉 run()의 수행이 종료된 쓰레드는 호출 스택이 모두 비워지며 이 호출스택은 사라진다.
main 메서드가 수행을 마치면 프로그램이 종료 되었으나, 다른 쓰레드가 아직 작업을 마치지 않은 상태이면 프로그램은 종료되지 않는다.
실행 중인 사용자 쓰레드가 하나도 없을 떄 프로그램은 종료된다.
호출스택의 첫 번쨰 메서드가 main메서드가 아니라 run 메서드인 것을 확인하자.
한 쓰레드의 예외가 발생해서 종료되어도 다른 쓰레드의 실행에는 영향을 주지 않는다. (독립적이다)
main 쓰레드는 이미 종료
start()가 없으므로 쓰레드가 새로 생성되지 않았다 (=호출 스택 새로 생성 x)
쓰레드가 생성된게 아니라 그냥 run()메서드만 호출 된것일뿐이다( 위의 예제와 차이점을 유의하자)
일하는 일꾼(쓰레드) 가많으면 작업이 더빨리 끝날줄 알았지만 작업전환 이란것 떄문에 시간이 더걸린다.
프로세스 또는 쓰레드 간의 작업 전환을 '컨텍스트 스위칭' 이라한다.
그래서 간단한 작업은 오히려 싱글 쓰레드가 더빠르다.
한 쓰레드가 화면에 출력하고 있는동안 다른 쓰레드는 출력이 끝나기를 기다려야 하기 떄문에 시간이 더 걸린다
싱글 코어 인경우 두 작업이 절대 겹치지 않지만 멀티 코어에 멀티 쓰레드인 경우에는 겹치는 부분이 발생한다. 그래서 화면(CONSOLE)라는 자원을 놓고 두 쓰레드가 경쟁하는 것이다.
-> 위의 결과는 실행할때마다 다른 결과를 얻는데 그 이유는 예제프로그램이 os의 프로세스 스케줄러의 영향을 받기 떄문
하!지!만!
하나의 자원(싱글win) vs 다른자원 (멀티쓰레드 win)
쓰레드가 수행하는 작업의 중요도에 따라 쓰레드의 우선순위를 서로 다르게 지정하여 특정 쓰레드가 더 많은 작업 시간을 갖도록 할수 있다.
쓰레드가 가질수 있는 우선순위의 범위는 1 부터 10 이며 숫자가 높을수록 우선순위가 높다.
우선순위는 쓰레드를 생성한 쓰레드로부터 상속 받는다.
main 메서드를 수행하는쓰레드는 우선순위가 5이다.
t1, t2 모두 main 메서드에서 생성하였기 떄문에 우선순위 5이다. t2는 setPriority(7)을 통해 우선순위를 7로 변경했다. 그다음 start()를 호출했다.
이 처럼 쓰레드를 실행하기 전에만 우선순위를 변경 할수 있다.
하지만 멀티코어에서는 쓰레드의 우선순위에 따른 차이가 전혀 없다... -> 우선순위에 차등을 두어 쓰레드를 실행시키는 것은 별 효과 없다.
=> 멀티 코어라 해도 os마다 다른 방식으로 스케쥴링 하기 떄문에 os마다 다른 결과가 나온다.