프로그래밍 언어/JAVA

Runnable 인터페이스 스레드 만들기

· 코딩마이데이

Runnable은 클래스가 아닌 인터페이스로서 경로명 java.lang.Runnable이며, 다음과 깉이 추상 메서드 run() 하나만 가지고 있습니다.

interface Runnable {
	public void run();
}

 

스레드 클래스 선언: Runnable 인터페이스 구현

Runnable 인터페이스를 구현하도록 TimerRunnable 클래스를 선언합니다.

class TimerRunnable implements Runable {
	................................
}

 

스레드 코드 작성: run() 메서드 오버라이딩

Runnable 인터페이스의 run() 메서드를 오버라이딩하여 스레드 코드를 작성합니다.

class TimerRunnable implments Runnable {
	@Override
	public void run() { // run() 메서드 오버라이딩
		.........................
	}
}

 

run() 메서드는 스레드 코드이며 run()이 종료돠면 스레드도 종료됩니다.

 

스레드 객체 생성

Thread 객체를 생성합니다. 이때 생성자에 TimerRunnable의 객체를 전달합니다.

Thread th = new Thread(new TimerRunnable());

 

이 코드는 생성한 스레드의 th의 스레드 코드로 TimerRunnable의 run()을 사용할 것을 알려줍니다.

 

스레드 시작: start() 메서드의 호출

마지막 과정으로 Thread 클래스의 start() 메서드를 호출하여 스레드를 시작하게 합니다.

th.start();

 

th.start()는 생성된 스레드 객체 th를 스케줄링이 가능한 상태로 전환하도록 JVM에게 지시합니다. 이후 JVM에 의해 이 스레드가 선택되면 이 스레드의 run() 메서드가 호출되고 실행됩니다.

Runnable 인터페이스를 상속받아 1초 단위로 초 시간을 출력하는 스레드 작성 예

 

 

Runnable 인터페이스를 이용하여 1초 단위로 출력하는 타이머 스레드 만들기

import javax.swing.*;
import java.awt.*;

class TimerRunnable implements Runnable{
    private JLabel timerLabel; // 타이머 값이 출력된 레이블

    public TimerRunnable(JLabel timerLabel) {
        this.timerLabel = timerLabel; // 초 카운트를 출력할 레이블
    }

    // 스레드 코드, run()이 종료하면 스레드 종료
    @Override
    public void run() {
        int n = 0; // 타이머 카운트 값
        while (true) { // 무한 루프
            timerLabel.setText(Integer.toString(n)); // 레이블에 카운트 값 출력
            n++; // 카운트 증가
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                return; // 예외가 발생하면 스레드 종료
            }
        }
    }
}

public class RunnableTimerEx extends JFrame{
    public RunnableTimerEx() {
        setTitle("Runnable을 구현한 타이머 스레드 에제");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Container c = getContentPane();
        c.setLayout(new FlowLayout());

        // 타이머 값을 출력할 레이블 생성
        JLabel timerLabel = new JLabel();
        timerLabel.setFont(new Font("Gothic", Font.ITALIC, 80));
        c.add(timerLabel); // 레이블을 컨텐트팬에 부착

        // 타이머 스레드로 사용할 Runnable 객체 생성. 타이머 값을 출력할 레이블을 생성자에 전달
        TimerRunnable runnable = new TimerRunnable(timerLabel);
        Thread th = new Thread(runnable); // 스레드 객체 생성ㅇ

        setSize(250, 150);
        setVisible(true);

        th.start(); // 타이머 스레드가 실행을 시작하게 한다.
    }

    public static void main(String[] args) {
        new RunnableTimerEx();
    }
}

 

[실행결과]

 

 

깜박하는 문자열을 가진 레이블 만들기

import javax.swing.*;
import java.awt.*;

class FlickeringLabel extends JLabel implements Runnable {
    private long delay; // 배경색이 바뀌는 지연 시간, 밀리초 단우;

    public FlickeringLabel(String text, long delay) { // 생성자
        super(text); // JLabel 생성자 호출
        this.delay = delay;
        setOpaque(true); // 배경색 변경이 가능하도록 설정

        Thread th = new Thread(this);
        th.start();
    }

    @Override
    public void run() {
        int n = 0;
        while (true) {
            if (n == 0)
                setBackground(Color.YELLOW);
            else
                setBackground(Color.GREEN);
            if (n == 0) n = 1;
            else n = 0;
            try {
                Thread.sleep(delay); // delay 밀리초 동안 잠을 잔다.
            }
            catch (InterruptedException e) {
                return;
            }
        }
    }
}

public class FlickeringLabelEx extends JFrame{
    public FlickeringLabelEx() {
        setTitle("FlickeringLabelEx 예제");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Container c = getContentPane();
        c.setLayout(new FlowLayout());

        FlickeringLabel fLabel = new FlickeringLabel("깜박", 500); // 500밀리초 주기로 배경색 변경

        // 깜박이지 않는 레이블 생성
        JLabel label = new JLabel("안깜박");

        // 깜박이는 레이블 생성
        FlickeringLabel fLabel2 = new FlickeringLabel("여기도 깜박", 300); // 300밀리초 주기로 배경색 변경

        c.add(fLabel);
        c.add(label);
        c.add(fLabel2);

        setSize(300, 150);
        setVisible(true);
    }

    public static void main(String[] args) {
        new FlickeringLabelEx();
    }
}

 

[실행결과]

 

 

스레드 정보

필드 타입 내용
스레드 이름 스트링 스레드의 이름으로서 사용자가 지정
스레드 ID 정수 스레드 고유의 식별자 번호
스레드의 PC(Program Count) 정수 현재 실행 중인 스레드 코드의 주소
스레드 상태 정수 NEW, RUNNABLE, WAITING, TIMED_WAITING, BLOCK, TERMINATED 등 6개 상태 중 하나
스레드 우선순위 정수 스레드 스케줄링 시 사용되는 우선순위 값으로서, 1~10 사이의 값이며 10이 최상위 우선순위
스레드 그룹 정수 여러 개의 자바 스레드가 하나의 그룹을 형성할 수 있으며 이 경우 스레드가 속한 그룹
스레드 레지스터 스택 메모리 블록 스레드가 실행되는 동안 레지스터들의 값

 

데몬 스레드(demon thread)와 사용자 스레드(user thread)

자바의 스레드는 두 가지 종류로 구분됩니다. 첫째는 데몬 스레드(demon thread)인데 응용프로그램이 실행되는 동안 관리를 위해 존재하는 스레드로, 가비지 컬렉션 스레드(garbage collector)가 대표적입니다. 둘째는 사용자 스레드(user thread)로서 응용 프로그램에서 생성한 스래드입니다. 사용자 스레드는 Thread 클래스의 setDaemon(true)을 호출하면 데몬 스레드로 바꿀 수 있습니다.

데몬 스레드가 사용자 스레드와 다른 점은, 대몬 스레드가 살아 있더라도 JVM 함께 응용프로그램도 종료된다는 점입니다.

'프로그래밍 언어 > JAVA' 카테고리의 다른 글

스레드 종료  (4) 2025.08.19
스레드 생명 주기와 스케줄링  (4) 2025.08.16
Thread 클래스를 상속받아 스레드 만들기  (1) 2025.08.10
자바의 멀티스레딩  (7) 2025.08.07
스레드와 멀티태스킹  (2) 2025.08.05