Programming/Process & Multi Threading

[Java] Runnable 인터페이스와 Thread 클래스

dev.pudding 2023. 12. 11. 22:34
728x90
목차 
1. Runnable 인터페이스 
2. Thread 클래스 
3. 시스템 로드에 따른 JVM의 자동 스레드 관리 

 

자바는 기본적으로 싱글스레드 환경으로 실행된다. 메인 메서드(main method)가 포함된 클래스의 main 스레드가 실행되며, 이는 싱글스레드에서 코드를 순차적으로 실행한다. 만약 멀티 스레드 환경으로 실행하고 싶은 경우 Runnable 인터페이스나 Thread 클래스를 사용한다. 

 

하지만 일부 자바 라이브러리 및 프레임워크 내부에서는 자동으로 멀티스레딩을 사용하여 작업을 실행하기도 한다(Stream API , 스프링 etc) 


1.Runnable 인터페이스 

The Runnable interface should be implemented by any class whose instances are
intended to be executed by a thread. The class must define a method of no arguments called run.

출처 : Oracle Javadoc

 

Runnable 인터페이스는 스레드로 실행시키고 싶은 인스턴스가 있을 때 구현해준다. 구현 시에는 run()이라는 메소드를 반드시 오버라이딩 해줘야 스레드 작업이 실행된다.

 

Runnable 인터페이스 코드예시 

class Runner1 implements Runnable{ // Runnable 인터페이스구현 

    @Override
    public void run(){ // run오버라이딩 
        for(int i=0;i<10;i++){
       	 System.out.println("Runner1:" + i ) ;
        }
    }
}

class Runner2 implements Runnable{

    @Override
    public void run(){
        for(int i=0; i<10; i++){
     	   System.out.println("Runner2 : " + i);
        }
    }
}

public class App{
    public static void main(String[] args){ // 실행메소드 


    Thread t1 = new Thread(new Runner1());//인자값으로 구현체를 주면 스레드 실행시 run메소드가 실행됨
    Thread t2 = new Thread(new RUnner2());

    Thread t3 = new Thread(new Runnable(){ //스레드당 run메소드는 하나라서 익명클래스쓰는것이 관례  
 
 	@Override
   	 public void run(){
        for(int i=0;i<10;i++){
            System.out.println("Runner3 : " + i);
          }
       }
  });

   // 스레드 실행 
    t1.start();
    t2.start();
    t3.start();


    }
}

 

결과

-> Runner1,Runner2,Runner3 이 순차적으로 실행되지 않고 멀티스레드 환경으로 작업이 실행되는 것을 볼 수 있다.


2. Thread 클래스 

A thread is a thread of execution in a program. The Java Virtual Machine allows an application to have multiple threads of execution running concurrently.

출처 : Oracle javadoc 

 

스레드(Thread)는 프로그램 내에서 실행되는 실행 스레드이다. JVM(자바가상머신)은 어플리케이션이 동시에 여러 실행 스레드를 가질 수 있도록 허용한다.

Runnable 인터페이스의 경우 run() 메소드 하나만 오버라이딩하여 사용했지만, Thread 객체를 직접 상속받은 클래스의 경우 run()메소드 외에도 sleep() , join()등 다양한 메소드를 사용할 수 있다. 

 

Thread 클래스 코드예시 

class Runner1 extends Thread{//Thread 클래스 상속 
	
    @Override
    public void run(){
        for(int i=0;i<10;i++){
            try{
                  Thread.sleep(1000); // 1초씩 멈추기 
                }catch(InterruptedException ex){
                        ex.printStackTrace();
                }
            System.out.println("Runner1 : " + i);
        }
  }
}


class Runner2 extends Thread{ 

    @Override
    public void run(){
            for(int i=0; i<10; i++){
                try{
                    Thread.sleep(1000);
                }catch(InterruptedException ex){
                        ex.printStackTrace();
                }
                System.out.println("Runner1 : " + i);
        }
    }
}

public class App{
    public static void main(String[] args){

        Thread t1 = new Runner1(); //인스턴스를 바로 가져와서 실행 
        Thread t2 = new Runner2();
        //스레드 실행 
        t1.start();
        t2.start();

    }
}

 

Thread 클래스를 직접 상속받았기때문에 run메소드외에도 sleep메소드를 사용하여 스레드를 잠시 멈추는 메소드를 사용했다   


3. 시스템 로드에 따른 JVM의 자동 스레드 관리

JVM은 시스템의 로드가 낮을 때 성능 최적화를 위해 자동으로 하나의 코어(싱글 코어)에서 멀티스레드를 실행한다. 이는 개발자가 명시적으로 설정하지 않아도 JVM이 내부적으로 자동으로 처리하는 기능이다.

싱글 코어에서 멀티스레드 작업을 수행할 때, CPU의 스케줄러는 여러 스레드 간에 작은 시간 조각을 번갈아가며 할당하여 마치 여러 스레드가 동시에 실행되는 것처럼 보이도록 하는 시분할 알고리즘(Time-Slicing algorithm)을 사용한다. 이는 동시성(concurrency) 이라고도 불린다.

동시성(concurrency)/시분할알고리즘(time-slicing)의 예시

 

 JVM은 시스템의 로드가 높다면 멀티코어 상태에서 병렬(parallel)로 멀티스레드를 실행한다.  시스템의 로드가 높은 Stream API와 스프링 프레임워크에서는  멀티코어를 활용하여 멀티스레드를 병렬로 실행시킨다.