[자바 (JAVA)] 52. Thread

귤's avatar
Feb 24, 2025
[자바 (JAVA)] 52. Thread

1. Thread란?

💡
프로세스 안에서 실질적으로 작업을 실행하는 단위
프로세스에는 적어도 한 개 이상의 Thread가 있다.
main Thread 하나에서 Thread를 추가 생성하게 되면 멀티 Thread 환경이 된다.

2. Thread의 생성자

1) Thread

  1. Thread() : 새로운 스레드 객체 할당
  1. Thread(String name) : 새로운 스레드 객체가 할당되며, 스레드 이름은 name으로 설정됨
  1. Thread(Runnable target) : Runnable target이 구현된 스레드 객체 할당
  1. Thread(Runnable target, String name) : Runnable target이 구현된 스레드 객체가 할당되면 스레드 이름은 name으로 설정됨

3. Thread를 사용하면 좋은 상황 👍

  1. 동시에 해야할 때
  1. I/O가 일어날 때

4. Thread 생성 방법

  1. Thread 클래스를 상속 받는 방법
  1. Runnable 인터페이스를 구현하는 방법

5. Thread 기본 1

package ex19; // 스레드 기본 (스레드 객체 생성, 스레드 시작, 타겟(run메소드) 만들기) public class Th01 { public static void sub1() { for (int i = 1; i <= 5; i++) { System.out.println("스레드 1 : " + i); try { Thread.sleep(500); } catch (InterruptedException e) { throw new RuntimeException(e); } } } public static void sub2() { for (int i = 1; i <= 5; i++) { System.out.println("스레드 2 : " + i); try { Thread.sleep(500); } catch (InterruptedException e) { throw new RuntimeException(e); } } } // class SSS implements Runnable { // public void run() { // } // } public static void main(String[] args) { // cpu -> 메인 쓰레드 Thread t1 = new Thread(() -> sub1()); // 한 줄이면 중괄호 생략 가능, run메소드 = (() -> sub1()), 타겟은 run t1.start(); new Thread(() -> sub2() // 타겟은 run ).start(); } }
notion image

6. Thread 기본 2

package ex19; public class Th02 { static String product = null; public static void main(String[] args) { Thread supp = new Thread(() -> { try { Thread.sleep(10000); product = "바나나깡"; } catch (InterruptedException e) { throw new RuntimeException(e); } }); supp.start(); Thread lis = new Thread(() -> { while (true) { try { Thread.sleep(500); if (product != null) { System.out.println("상품이 입고되었습니다. : " + product); break; } } catch (InterruptedException e) { throw new RuntimeException(e); } } }); lis.start(); } }

7. Thread 동시 작업 처리 예제

package ex19; class MyFile { public void write() { try { Thread.sleep(5000); System.out.println("파일 쓰기 완료"); } catch (InterruptedException e) { throw new RuntimeException(e); } } } class 화가 { public void 그림그리기() { System.out.println("그림 그리기 완료"); } } // 화가 public class Th03 { public static void main(String[] args) { MyFile myFile = new MyFile(); 화가 painter = new 화가(); painter.그림그리기(); new Thread(() -> { myFile.write(); }).start(); painter.그림그리기(); } }

8. Class로 Thread 만들기

package ex19; import java.util.ArrayList; import java.util.List; // 1. 상속받고 2. 타겟 재정의 class MyThread extends Thread { private List<Integer> list; @Override public void run() { // 타겟 재정의 for (int i = 0; i < 10; i++) { System.out.println("MyThread : " + i); try { Thread.sleep(500); } catch (InterruptedException e) { throw new RuntimeException(e); } } } public MyThread(List<Integer> list) { this.list = list; } public void addList(int num) { list.add(num); } public List<Integer> getList() { return list; } } // 클래스로 스레드 만들기 (스레드별 상태 보관) public class Th04 { public static void main(String[] args) { MyThread t1 = new MyThread(new ArrayList<>()); // MyThread는 ArrayList에 의존한다. t1.start(); } }

9. Thread 숫자 카운터 프로그램 예제

package ex19; import javax.swing.*; public class Th05 extends JFrame { // JFrame = 자바에서 그림그리는 도구 private boolean state = true; private int count = 0; private int count2 = 0; private JLabel countLabel; private JLabel count2Label; public Th05() { setTitle("숫자 카운터 프로그램"); setVisible(true); setSize(300, 200); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 레이아웃 매니저 설정 setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); // 숫자를 표시할 레이블 생성 countLabel = new JLabel("숫자1: " + count); count2Label = new JLabel("숫자2: " + count2); countLabel.setAlignmentX(CENTER_ALIGNMENT); count2Label.setAlignmentX(CENTER_ALIGNMENT); add(countLabel); add(count2Label); // 멈춤 버튼 생성 JButton increaseButton = new JButton("멈춤"); increaseButton.setAlignmentX(CENTER_ALIGNMENT); add(increaseButton); // 버튼에 액션 리스너 추가 increaseButton.addActionListener(e -> { state = false; }); new Thread(() -> { while (state) { try { Thread.sleep(1000); count++; countLabel.setText("숫자1 : " + count); } catch (InterruptedException ex) { throw new RuntimeException(ex); } } }).start(); new Thread(() -> { while (state) { try { Thread.sleep(1000); count2++; count2Label.setText("숫자2 : " + count2); } catch (InterruptedException ex) { throw new RuntimeException(ex); } } }).start(); } public static void main(String[] args) { new Th05(); } }

10. Thread가 return해야 할 때 (첫번째 방법)

package ex19; //콜백 class Store implements Runnable { int qty; @Override public void run() { // 통신 -> 다운로드 try { Thread.sleep(100); } catch (InterruptedException e) { throw new RuntimeException(e); } qty = 5; } } /* 스레드에서 받은 데이터를 리턴 받아서 응용하고 싶을때!! 1. 타이밍 맞추기 (임시방편 - 그래도 쓰는 사람 많음) 2. 리스너 (부하가 너무 큼) 3. 콜백 (제일 좋음) */ // 사용 이유 : 동시에 해야할 때, I/O가 일어날 때!! public class Th06 { public static void main(String[] args) { int totalQty = 10; Store store = new Store(); Thread t1 = new Thread(store); t1.start(); try { Thread.sleep(200); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println("재고수량 :" + (store.qty + totalQty)); } }

11. Thread가 return해야 할 때 (두번째 방법)

package ex19; //콜백 class Store implements Runnable { Integer qty; @Override public void run() { // 통신 -> 다운로드 try { Thread.sleep(100); } catch (InterruptedException e) { throw new RuntimeException(e); } qty = 5; } } /* 스레드에서 받은 데이터를 리턴 받아서 응용하고 싶을때!! 1. 타이밍 맞추기 (임시방편 - 그래도 쓰는 사람 많음) 2. 리스너 (부하가 너무 큼) 3. 콜백 (제일 좋음) */ // 사용 이유 : 동시에 해야할 때, I/O가 일어날 때!! public class Th06 { public static void main(String[] args) { int totalQty = 10; Store store = new Store(); Thread t1 = new Thread(store); t1.start(); while (true) { if (store.qty != null) break; try { Thread.sleep(10); System.out.println(store.qty + "지켜본다"); } catch (InterruptedException e) { throw new RuntimeException(e); } } System.out.println("재고수량 :" + (store.qty + totalQty)); } }
notion image

12. Thread 콜백 메소드 활용

package ex19; //콜백 // [1] 콜백 메소드 만들기 interface Callback { void 입고(int qty); // 괄호 안에는 리턴 받고 싶은 인수를 만들어주면 된다. = 정확하게는 파라미터 } class Store implements Runnable { // [2] 리턴이 필요한 곳으로 가서 콜백 메소드 전달 받기 Integer qty; Callback callback; public Store(Callback callback) { this.callback = callback; } @Override public void run() { // 통신 -> 다운로드 try { Thread.sleep(100); } catch (InterruptedException e) { throw new RuntimeException(e); } qty = 5; callback.입고(qty); // [3] 종료시 콜백 메소드 호출 } } /* 스레드에서 받은 데이터를 리턴 받아서 응용하고 싶을때!! 1. 타이밍 맞추기 (임시방편 - 그래도 쓰는 사람 많음) 2. 리스너 (부하가 너무 큼) 3. 콜백 (제일 좋음) */ // 사용 이유 : 동시에 해야할 때, I/O가 일어날 때!! public class Th06 { public static void main(String[] args) { int totalQty = 10; Store store = new Store(qty -> { System.out.println("재고수량 :" + (qty + totalQty)); }); Thread t1 = new Thread(store); t1.start(); } }
notion image
Share article

gyul