포트폴리오/[IoT 기반 피지컬 AI 교육일지]

[ JAVA 기초 ] 자바 스레드 구현 (32일차 기록)

개발자혜콩 2026. 4. 9. 09:44

1. 오늘 한 것

① 자바 멀티스레드(Thread) 구현 2가지 방식

Java에서 스레드를 생성하고 실행하는 두 가지 표준 접근법을 코드로 실습함.

  • (1) Thread 클래스 상속 (extends Thread):
    • 스레드 클래스를 직접 상속받아 run() 메서드를 오버라이딩하는 직관적인 방식. (예: 1~100 숫자 출력)
  • (2) Runnable 인터페이스 구현 (implements Runnable):
    • 구현체 클래스를 만들고, 이를 Thread 객체의 생성자 매개변수로 넘겨 실행하는 방식. (예: A~Z 알파벳 출력)

 

② 배열 매개변수 전달 및 탐색 (printMax)

  • 정수형 배열을 메서드의 인자로 전달하여 배열 내 최댓값을 찾는 알고리즘 구현.
// Java 스타일의 배열 선언 및 넘기기
int[] array = {4, 5, 8, 1, 2, 3, 7};
printMax(array);

// 최댓값을 찾는 메서드
public static void printMax(int[] arr) {
    int max = arr[0];
    for (int i = 1; i < arr.length; i++) {
        if (arr[i] > max) max = arr[i];
    }
    System.out.println("가장 큰 값 : " + max);
}

 

③ 메서드 매개변수 전달 방식 연구 (Swap 실습)

  • 두 변수의 값을 서로 바꾸는 Swap(int a, int b) 함수를 만들며 Java의 메모리 참조 방식을 C언어와 비교 분석.

2. 문제 / 헷갈린 점

① Thread 상속 vs Runnable 인터페이스 구현, 무엇을 써야 할까?

  • 상황: 기능이 똑같은데 왜 굳이 두 가지 방식이 나뉘어 있는지 의문이 들었음.
  • 해결: Java는 C++과 달리 '다중 상속'을 지원하지 않음. 만약 내 클래스가 이미 다른 부모 클래스(extends OtherClass)를 상속받고 있다면 Thread를 상속받을 수 없게 됨. 이럴 때 유연하게 스레드를 붙일 수 있도록 implements Runnable 방식을 제공하는 것임을 이해함.

② C언어와 다른 배열 선언 문법 혼동

  • 상황: 문제에서 int array[7] = { ... } 형태로 주어졌는데, Java에서는 주로 크기를 대괄호 안에 명시하지 않는 문법을 씀.
  • 해결: Java의 올바른 배열 선언은 int[] array = { 4, 5, 8, 1, 2, 3, 7 }; 임을 상기함. 배열을 객체로 취급하기 때문에 C언어처럼 선언 시 크기를 하드코딩하지 않아도 내부적으로 길이를 관리함(arr.length).

③ Java의 함정: 기본 자료형의 Swap은 불가능하다 (Call by Value)

  • 상황: Util.swap(a, b)를 만들어 두 정수를 넘겼는데, 함수 안에서는 값이 바뀌어도 main 함수로 돌아와서 출력해 보면 원본 a, b의 값이 그대로 100, 200으로 유지되는 현상 발생. 포인터(*, &)가 없어서 당황함.
  • 해결: Java의 기본 자료형(int, double, char 등)은 100% 'Call by Value(값에 의한 복사)'로만 동작함. 즉, 변수 공간을 공유하는 게 아니라 값만 복사해서 넘겨주기 때문에 함수 안에서 지지고 볶아도 원본은 타격을 입지 않음.
  • 대안: 원본을 바꾸려면 기본 자료형 대신 배열 크기가 1인 배열(int[])에 담아 넘기거나, 값을 멤버 변수로 갖는 **객체(Object)**를 넘겨 참조 주소(Reference)를 건드리는 방식으로 우회해야 함.

3. 오늘 배운 핵심

① 스레드 실행의 규칙:

스레드를 동작시킬 때는 내가 정의한 run() 메서드를 직접 부르는 게 아니라, 반드시 start()를 호출해야 운영체제가 스레드를 별도로 생성해 병렬로 실행시켜 준다.

 

② 유연한 설계를 위한 Runnable:

다중 상속이 불가능한 Java의 특성상, 스레드 구현 시에는 extends Thread보다 implements Runnable을 사용하는 것이 객체지향적으로 훨씬 유리하다.

 

③ Java에는 포인터가 없다:

메서드에 인자를 넘길 때 기본 자료형은 '값의 복사', 객체나 배열은 '주소(참조)의 복사'가 일어남을 명확히 구분해야 의도치 않은 버그를 막을 수 있다.


4. 다음 목표

  • 이틀간의 압축적인 Java 핵심 문법 리뷰를 마치고, 드디어 본격적인 Android Studio 개발 환경 세팅하기.
  • Android 앱의 뼈대가 되는 XML 기반 레이아웃(Layout) 구조 살펴보기.