본문 바로가기
프로그래밍/자바

자바 쓰레드(Thread)

by 밍구몬 2019. 3. 1.

쓰레드란?

 

스레드란 실행 단위다. main() 메소드를 만들면 main() 메소드룰 실행하는 하나의 스레드가 생긴다.

스레드를 사용하게 되면 보다 빠른 처리가 가능하다. 하나의 응용프로그램을 여러 개의 스레드로 구성하면 스레드 사이의 문맥 교환 시 작업량이 작고 시간이 짧은 장점을 가진다.

인터넷 브라우저로 예를 들면 멀티 스레딩을 통해 검색을 하며 인쇄도 할 수 있고, 인터넷으로 영화도 볼 수 있다. 만약 인터넷 브라우저가 싱글 스레드로 구성되어 있다면 검색을 하는중에는 영화는 볼 수 없으며 인쇄도 할 수 없다. 

 

Thread의 상태

 
 
 

 

  • NEW : 스레드가 객체가 생성됨, 아직 실행되지 않은 상태
  • RUNNABLE : 스레드가 실행되기 위한 준비단계
  • WAITING : 다른 스레드가 통지할 때까지 기다리는 상태
  • TIMED_WAITING : 주어진 시간 동안 기다리는 상태
  • BLOCKED : 객체 잠금이 풀릴 때까지 기다리는 상태
  • TERMINATED : 실행을 마친 상태

 

Thread Class

 

클래스 경로명 java.lang.Thread

 

Thread 메소드

내용

Thread()

단순한 스레드 객체 생성

Thread(Runnable target)

Runnable 객체인 target을 이용하여 스레드 객체 생성

Thread(String name)

이름이 name인 스레드 객체 생성

Thread(Runnable target,String name)

Runnable 객체를 이용하며, 이름이 name인 스레드 객체 생성

void run()

스레드 코드로서 JVM에 의해 호출된다. 반드시 오버라이딩하여 스레드 코드를 작성하여야 한다. 이 메소드가 종료하면 스레드도 종료

void start()

JVM에게 스레드를 실행을 시작하도록 요청(run() 메소드 호출)

Void interrupt()

스레드 강제 종료

Static void yield()

다른 스레드에게 실행을 양보

void join()

스레드가 종료될 때까지 기다린다.

long getId()

스레드의 ID값 리턴

String getName()

스레드의 이름 리턴

int getPriority()

스레드의 우선순위 값 리터

void setPriority(int n)

스레드의 우선순위 값을 n으로 변경

Thread.State getState()

스레드의 상태 값 리턴

static void sleap(long m)

m밀리초만큼 sleep

static Thread currentThread()

현재 실행 중인 스레드 객체의 래퍼런스 리턴

boolean isAlive()

스레드가 실행중이면 True 끝났으면 False 리턴

void suspend()

스레드 일시정지

void resume()

일시 정지된 스레드 다시 실행


Thread 예제

import java.lang.Thread;

 

class Sum{

int num=0;

int sum(){

for(int i=0;i<1000;i++) {

num+=1;

}

return num;

}

}

 

class ThreadEX extends Thread{

 

Sum s = new Sum();

public void run() {

String threadName = Thread.currentThread().getName(); //쓰레드 이름 받아오기

System.out.println(threadName+" : "+s.sum());

}

}

 

public class Main {

public static void main(String[] args) {

 

ThreadEX t = new ThreadEX();

Thread ex1 = new Thread(t,"a"); //첫번째 쓰레드 객체 생성 쓰레드 이름은 a

Thread ex2 = new Thread(t,"b"); //두번째 쓰레드 객체 생성 쓰레드 이름은 b

 

//멀티 쓰레드 시작

ex1.start();

ex2.start();

}

}

 

실행 결과

 

  • 위와 같이 상속을 받아서 쓰레드를 사용할 수도 있지만, 상속은 한개 밖에 받을 수 없기에 Runnable 인터페이스를 주로 사용한다. Runnable은 추상 메소드 run()만 가지고 있다.

 

Runnable 사용 예제

 

import java.lang.Thread;

 

class Sum{

int num=0;

int sum(){

for(int i=0;i<1000;i++) {

num+=1;

}

return num;

}

}

 

class ThreadEX implements Runnable{

 

Sum s = new Sum();

public void run() {

String threadName = Thread.currentThread().getName(); //쓰레드 이름 받아오기

System.out.println(threadName+" : "+s.sum());

}

}

 

public class Main {

public static void main(String[] args) {

 

Runnable r = new ThreadEX();

Thread ex1 = new Thread(r,"a"); //첫번째 쓰레드 객체 생성 쓰레드 이름은 a

Thread ex2 = new Thread(r,"b"); //두번째 쓰레드 객체 생성 쓰레드 이름은 b

//위에서는 쓰레드의 이름을 설정해 주었지만 설정하지 않을 경우 Thread(r); 로 사용하면 된다.

 

//멀티 쓰레드 시작

ex1.start();

ex2.start();

}

}

 

실행 결과

 

 


 

 

위의 예제들을 보면 실행결과가 예상햇던 것과는 다르게 나왔을 것이다.  그 이유는 스레드를 동기화해주지 않았기 때문이다.

동기화를 안해주게 되면 쓰레드 ex1이 Sum클래스의 num에 접근 했을 때 동시에 ex2도 접근하는 일이 생기기 때문이다. 그렇기 때문에 예상했던 2000과는 다른 결과가 나오게 된것이다.

 

멀티 쓰레드 동기화에 관해서는 다음 글에서 설명하겠다.

https://ming9mon.tistory.com/44