Backend boot camp/Session1
[JAVA] 심화 - Thread, JVM
by orioncsy
2022. 9. 19.
0. 스레드
개요
학습 목표
스레드란
싱글 스레드 VS 멀티 스레드
스레드 생성 방법
스레드 실행 및 동기화
스레드 상태 및 제어
스레드란?
프로세스
운영체제가 할당한 메모리에 실행 중인 애플리케이션
데이터, 컴퓨터 자원, 스레드로 구성
스레드
프로세스 내 소스 코드의 실행 흐름
멀티 스레드로 동시 작업 실행 가능
메인 스레드(Main thread)
자바 애플리케이션에서 메인 메서드를 가장 먼저 실행
메인 메서드 안의 코드를 실행시키는 메인 스레드
메인 스레드만 사용하면 싱글 스레드
멀티 스레드(Multi thread)
여러 개의 스레드가 동시 작업
하나의 애플리케이션 내 여러 작업을 동시에 실행
스레드 생성과 실행
Runnable 인터페이스에서 run() 메서드를 구현하여 스레드 생성
public class Main {
public static void main (String[] args) {
Thread thread1 = new Thread(new Task());
thread1.start();
for (int i=0 ; i<200 ; i++)
System.out.print("main_thread" );
}
}
class Task implements Runnable {
@Override
public void run () {
for (int i=0 ; i<200 ; i++)
System.out.print("thread1" );
}
}
익명 클래스를 활용하여 Runnable 인터페이스에서 run() 메서드를 구현
public class Main {
public static void main (String [] args ) {
Thread thread1 = new Thread(new Runnable ( ) {
@Override
public void run ( ) {
for (int i=0 ; i<200 ; i++)
System.out.print("thread1" );
}
});
thread1.start();
for (int i=0 ; i<200 ; i++)
System.out.print("main_thread" );
}
}
Thread 클래스를 상속 받은 하위 클래스에서 run() 구현하여 스레드 생성
public class Main {
public static void main (String[] args) {
Thread thread2=new Task2();
thread2.start();
for (int i=0 ; i<200 ; i++)
System.out.print("main_thread" );
}
}
class Task2 extends Thread {
@Override
public void run () {
for (int i=0 ; i<200 ; i++)
System.out.print("thread1" );
}
}
Thread 익명 하위 객체를 이용한 스레드 생성
public class Main {
public static void main (String [] args ) {
Thread thread2=new Task2 ( ) {
@Override
public void run ( ) {
for (int i=0 ; i<200 ; i++)
System.out.print("thread1" );
}
};
thread2.start();
for (int i=0 ; i<200 ; i++)
System.out.print("main_thread" );
}
}
스레드 이름
메인 스레드는 main, 그 외의 스레드는 thread-n의 이름을 가진다
스레드 이름 조회
public class Main {
public static void main (String [] args ) {
Thread thread1 = new Thread(new Runnable ( ) {
@Override
public void run ( ) {
System.out.println("get thread name.." );
}
});
thread1.start();
System.out.println(thread1.getName());
}
}
스레드 이름 설정
public class Main {
public static void main (String [] args ) {
Thread thread1 = new Thread(new Runnable ( ) {
@Override
public void run ( ) {
System.out.println("set thread name" );
}
});
thread1.start();
thread1.setName("0th thread" );
System.out.println(thread1.getName());
}
}
스레드 인스턴스의 주소값
public class Main {
public static void main (String [] args ) {
Thread thread1 = new Thread(new Runnable ( ) {
@Override
public void run ( ) {
System.out.println(Thread.currentThread().getName());
}
});
thread1.start();
System.out.println(Thread.currentThread().getName());
}
}
스레드 동기화
스레드 동기화
두 개 이상의 스레드가 같은 데이터를 공유하여 발생하는 문제를 해결
synchronized()로 임계 영역(critical section)을 설정하고 하나의 스레드만 실행 가능한 구역으로 만든다
해당 임계 영역에 접근할 수 있는 권한인 lock을 획득한 스레드만 임계 영역을 실행 가능
스레드 동기화 방식
메서드 전체를 임계 영역으로 설정
public synchronized void method(){…}
특정 영역을 임계 영역으로 설정
스레드 상태 및 제어
.start()는 스레드를 실행 대기 상태로 올린다
스레드의 상태가 존재하고 제어하는 메서드들 존재
스레드 상태
스레드 생성(new)
실행 대기(runnable)
실행
일시정지
소멸
스레스 실행 제어 메서드
static void sleep(long millisecond) : millisecond 동안 스레드 일시정지
void interrupt() : 실행 대기로 복귀
wait, sleep, join으로 일시 정지한 스레드를 실행 대기 상태로 복귀
wait, sleep, join의 예외가 발생하여 일시정지 해제
예제
public class Main {
public static void main (String [] args ) {
Thread thread1 = new Thread(new Runnable ( ) {
@Override
public void run ( ) {
try {
while (true ){
Thread.sleep(1000 );
}
}
catch (Exception e){
System.out.println("interrupted now" );
}
}
});
System.out.println(thread1.getState());
thread1.start();
while (true ){
if (thread1.getState() == Thread.State.TIMED_WAITING) {
System.out.println(thread1.getState());
break ;
}
}
thread1.interrupt();
while (true ){
if (thread1.getState() == Thread.State.RUNNABLE) {
System.out.println(thread1.getState());
break ;
}
}
while (true ) {
if (thread1.getState() == Thread.State.TERMINATED) {
System.out.println(thread1.getState());
break ;
}
}
}
}
static void yield() : 다른 스레드에게 실행 양보
실행 상태에서 다른 스레드에게 실행을 양보
예제
public void run ( ) {
while (true ){
if (...){
...
}
else
Thread.yield ();
}
}
void join() / void join(long millisecond) : 다른 스레드의 작업이 끝날 때까지 기다림
sleep()과 유사하지만 join()은 특정 스레드에 대하여 작동하는 인스턴스 메서드다
notify(), wait() : 두 스레드가 교대로 작업할 때 사용
notify()로 다른 스레드를 실행 대기 상태로 두고 wait로 자신을 일시정지로 바꾸며 교대
public class Main {
public static void main (String[] args) {
Working working = new Working();
Thread1 thread1= new Thread1(working);
Thread2 thread2= new Thread2(working);
thread1.start();
thread2.start();
}
}
class Working {
public synchronized void method1 () {
System.out.println("this is method1" );
notify();
try {
wait();
} catch (Exception e) {};
}
public synchronized void method2 () {
System.out.println("this is method2" );
notify();
try {
wait();
} catch (Exception e) {};
}
}
class Thread1 extends Thread {
Working working;
public Thread1 (Working working) {
this .working = working;
}
@Override
public void run () {
for (int i=0 ; i<20 ; i++)
working.method1();
}
}
class Thread2 extends Thread {
Working working;
public Thread2 (Working working) {
this .working = working;
}
@Override
public void run () {
for (int i=0 ; i<20 ; i++)
working.method2();
}
}
1. 자바 가상 머신(Java Virtual Machine)
개요
Write once, run anywhere
JAVA는 JVM을 통해 운영체제에 독립적으로 프로그래밍 가능
학습 목표
JVM이란?
JVM 메모리 구조
Garbage Collection
JVM이란?
Java Virtual Machine
자바로 작성된 소스 코드를 실행하는 프로그램
프로그램이 실행되기 위해서 컴퓨터 자원을 요청
운영체제마다 방식이 다름
java는 JVM을 통해 각 운영체제에 맞게 변환시켜준다
JVM 구조
java source code(.java)
java Byte code(.class file)
java 파일을 javac라는 명령어로 java compiler를 사용하여 변환
JVM
runtime data area : 소스 코드에 필요한 메모리 할당
class loader : java Byte code를 runtime data area에 적재
execution engine : runtime data area에 적재된 byte code를 실행
interpreter : 코드를 한 줄씩 기계어로 번역하고 실행
JIT(just-in-time) Compiler : 전체 코드를 기계어로 번역하고 실행
기본적으로 interpreter를 사용하고 반복되는 코드를 JIT로 실행
Stack과 Heap
Java 메모리 구조
Runtime data area
method area
heap area
stack area
PC register
Native method stack
Stack
LIFO(Last In First Out) 방식의 자료구조
JVM 내 stack
메서드가 실행되면 method frame이 생성
매겨변수, 지역변수, 연산 값 등이 스택 형태로 저장
메서드가 종료될 때 역순으로 제거된다
Heap
JVM 내 하나의 heap 영역 존재
인스턴스를 생성하여 저장하는 장소
Garbage Collection
Garbage Collection
메모리 자동 관리 프로세스
더 이상 사용하지 않는 객체를 삭제
아무도 참조하고 있지 않는 객체를 제거
동작 방식
힙 영역 내에 객체가 얼마나 살아있냐에 따라 young, old 방식 존재
Young 영역
새롭게 생성된 객체가 할당되고 생성, 삭제가 반복되는 곳
Minor GC라고 부름
Old 영역
상태를 유지하고 남은 객체들이 복사되는 곳으로 크기가 크고 삭제할 데이터가 적다
Major GC라고 부름
기본적인 동작 방식
Stop The World
GC를 실행하기 위한 스레드를 제외한 모든 애플리케이션 실행을 중단
GC가 완료되면 재개
Mark and Sweap
메모리가 사용되고 있는지 식별(Mark)하고
사용되지 않는다면 제거(Sweep)한다
공유하기
URL 복사 카카오톡 공유 페이스북 공유 엑스 공유