🐯[TIL] 250623-016

byoΒ·2025λ…„ 6μ›” 23일

πŸ’« JAVA

βœ”οΈ 병렬 처리 Multi Threading

βœ… 병렬 μ²˜λ¦¬λž€?

  • ν•˜λ‚˜μ˜ 큰 μž‘μ—…μ„ μ—¬λŸ¬ 쑰각으둜 λ‚˜λˆ„μ–΄ λ™μ‹œμ— μ²˜λ¦¬ν•˜λŠ” λ°©μ‹μž…λ‹ˆλ‹€.
  • μ—¬λŸ¬ CPU μ½”μ–΄λ₯Ό ν™œμš©ν•΄ μž‘μ—… 속도λ₯Ό 높일 수 μžˆμŠ΅λ‹ˆλ‹€.

βœ… SumThread 클래슀 생성

  • λ°°μ—΄μ˜ 일뢀뢄을 ν•©μ‚°ν•˜λŠ” μŠ€λ ˆλ“œλ₯Ό λ§Œλ“€κΈ° μœ„ν•΄ Thread 클래슀λ₯Ό μƒμ†ν•œ SumThread 클래슀λ₯Ό μ •μ˜ν•©λ‹ˆλ‹€.
  • start와 end ꡬ간을 λ°›μ•„ ν•΄λ‹Ή κ΅¬κ°„μ˜ 합계λ₯Ό κ³„μ‚°ν•©λ‹ˆλ‹€.
class SumThread extends Thread {
    private int[] array;
    private int start, end;
    private int partialSum = 0;

    public SumThread(int[] array, int start, int end) {
        this.array = array;
        this.start = start;
        this.end = end;
    }

    public void run() {
        for (int i = start; i < end; i++) {
            partialSum += array[i];
        }
    }

    public int getPartialSum() {
        return partialSum;
    }
}

βœ… λ°°μ—΄ 생성 및 λΆ„ν• 

  • 크기 100의 배열을 λ§Œλ“€κ³  1λΆ€ν„° 100κΉŒμ§€ 값을 μ±„μ›λ‹ˆλ‹€.
  • 4개의 μŠ€λ ˆλ“œκ°€ 각자 25개의 값을 μ²˜λ¦¬ν•  수 μžˆλ„λ‘ 배열을 λΆ„ν• ν•  μ€€λΉ„λ₯Ό ν•©λ‹ˆλ‹€.
int[] numbers = new int[100];
for (int i = 0; i < numbers.length; i++) {
    numbers[i] = i + 1;
}

int numThreads = 4;
int chunkSize = numbers.length / numThreads;
SumThread[] threads = new SumThread[numThreads];

βœ… joinκ³Ό μ΅œμ’… ν•©μ‚°

  • λͺ¨λ“  μŠ€λ ˆλ“œκ°€ μž‘μ—…μ„ 끝낼 λ•ŒκΉŒμ§€ join()으둜 λŒ€κΈ°ν•œ ν›„,
    각 μŠ€λ ˆλ“œκ°€ κ³„μ‚°ν•œ 값을 λ”ν•΄μ„œ 전체 합계λ₯Ό κ΅¬ν•©λ‹ˆλ‹€.
int totalSum = 0;
try {
    for (SumThread thread : threads) {
        thread.join();
        totalSum += thread.getPartialSum();
    }
} catch (InterruptedException e) {
    System.out.println("Thread interrupted: " + e.getMessage());
}

System.out.println("Total sum: " + totalSum);

✏️ 톡합

class SumThread extends Thread {
    private int[] array;
    private int start, end;
    private int partialSum = 0;

    public SumThread(int[] array, int start, int end) {
        this.array = array;
        this.start = start;
        this.end = end;
    }
    public void run() {
        for (int i = start; i < end; i++) {
            partialSum += array[i];
        }
    }
    public int getPartialSum() {
        return partialSum;
    }
}

public class Main {
    public static void main(String[] args) {
        int[] numbers = new int[100];
        for (int i = 0; i < numbers.length; i++) {
            numbers[i] = i;
        }
        
        int numThreads = 4; // 덩어리 = 4개
        int chunkSize = numbers.length / numThreads; // ν•œ 덩어리 크기 = 25
        SumThread[] threads = new SumThread[numThreads]; // 덩어리 4개 λ“€μ–΄μžˆλŠ” SumThread[]

        for (int i = 0; i < numThreads; i++) {
            int start = i * chunkSize;
            int end = (i == numThreads - 1) ? numbers.length : start + chunkSize;
            // start = 0, 25, 50, 75
            // end = 25, 50, 75, 100

            threads[i] = new SumThread(numbers, start, end);
            threads[i].start();
        }

        int totalSum = 0;
        try {
            for (SumThread thread : threads) {
                thread.join();
                totalSum += thread.getPartialSum();
            }
        } catch (InterruptedException e) {
            System.out.println("Interrupted : " + e.getMessage());
        }

        System.out.println("Total sum : " + totalSum);
    }
}

βœ… 병렬 처리의 효과

  • 큰 데이터λ₯Ό μ—¬λŸ¬ λΆ€λΆ„μœΌλ‘œ λ‚˜λˆ  λ™μ‹œμ— μ²˜λ¦¬ν•˜λ©΄ 속도λ₯Ό 크게 ν–₯μƒμ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€.
  • 이미지 λ Œλ”λ§, λŒ€μš©λŸ‰ 파일 처리, κ³Όν•™ 계산 λ“± λ‹€μ–‘ν•œ λΆ„μ•Όμ—μ„œ μ‚¬μš©λ©λ‹ˆλ‹€.

πŸ” Thread λΆ„μ‚° 계산 ꡬ쑰 μš”μ•½

단계섀λͺ…
λ°°μ—΄ 쀀비계산할 데이터λ₯Ό λ°°μ—΄λ‘œ 쀀비함
Thread 생성배열을 λ‚˜λˆ  start~end λ²”μœ„λ₯Ό μ„€μ •ν•΄ μŠ€λ ˆλ“œ 생성
Thread 싀행각 μŠ€λ ˆλ“œκ°€ μžμ‹ μ΄ 맑은 ꡬ간을 λ³‘λ ¬λ‘œ 계산함
join 호좜λͺ¨λ“  μŠ€λ ˆλ“œκ°€ μ’…λ£Œλ  λ•ŒκΉŒμ§€ κΈ°λ‹€λ¦Ό
ν•©μ‚° 처리각 μŠ€λ ˆλ“œμ˜ κ²°κ³Όλ₯Ό λͺ¨μ•„ μ΅œμ’… 합계λ₯Ό 계산함

βœ… 였늘의 ν•œ 쀄 μš”μ•½
λ©€ν‹°μŠ€λ ˆλ“œλ₯Ό μ‚¬μš©ν•œ 병렬 μ²˜λ¦¬λŠ” μ—°μ‚° 속도λ₯Ό κ·ΉλŒ€ν™”ν•  수 μžˆλŠ” κ°•λ ₯ν•œ λ„κ΅¬μž…λ‹ˆλ‹€.


βœ”οΈ Annotation

βœ… μ–΄λ…Έν…Œμ΄μ…˜μ΄λž€?

  • μ–΄λ…Έν…Œμ΄μ…˜μ€ μ½”λ“œ μœ„μ— λΆ™μ—¬μ„œ μ»΄νŒŒμΌλŸ¬λ‚˜ 개발 도ꡬ에 정보λ₯Ό μ „λ‹¬ν•˜λŠ” λ¬Έλ²•μž…λ‹ˆλ‹€.
  • μ£Όμ„μ²˜λŸΌ λ³΄μ΄μ§€λ§Œ μ‹€μ œλ‘œ κΈ°λŠ₯이 있으며, μ½”λ“œμ˜ 의미λ₯Ό λͺ…ν™•νžˆ μ „λ‹¬ν•˜κ³  μ‹€μˆ˜λ₯Ό 쀄이며 μœ μ§€λ³΄μˆ˜μ— 도움을 μ€λ‹ˆλ‹€.

βœ… @Override

  • λΆ€λͺ¨ 클래슀의 λ©”μ„œλ“œλ₯Ό μžμ‹ ν΄λž˜μŠ€μ—μ„œ μž¬μ •μ˜ν•  λ•Œ μ‚¬μš©ν•©λ‹ˆλ‹€.
  • λ©”μ„œλ“œ μ‹œκ·Έλ‹ˆμ²˜κ°€ λ‹€λ₯Ό 경우 컴파일 μ—λŸ¬λ‘œ μ˜€λ²„λΌμ΄λ”© 였λ₯˜λ₯Ό μ•Œλ €μ€λ‹ˆλ‹€.

βœ… @Deprecated

  • 더 이상 μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” λ©”μ„œλ“œλ‚˜ ν΄λž˜μŠ€μ— λΆ™μž…λ‹ˆλ‹€.
  • λ‹€λ₯Έ κ°œλ°œμžμ—κ²Œ ν•΄λ‹Ή μš”μ†Œκ°€ ν–₯ν›„ 제거될 수 μžˆμŒμ„ μ•Œλ €μ€λ‹ˆλ‹€.

βœ… @SuppressWarnings

  • 컴파일러의 κ²½κ³  λ©”μ‹œμ§€λ₯Ό 숨기고 싢을 λ•Œ μ‚¬μš©ν•©λ‹ˆλ‹€.
  • 특히 μ œλ„€λ¦­ νƒ€μž… λ―Έμ§€μ •, μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” λ³€μˆ˜ 등에 자주 μ‚¬μš©λ©λ‹ˆλ‹€.

βœ… @FunctionalInterface

  • ν•˜λ‚˜μ˜ 좔상 λ©”μ„œλ“œλ§Œ ν¬ν•¨ν•˜λŠ” μΈν„°νŽ˜μ΄μŠ€μ— μ‚¬μš©ν•©λ‹ˆλ‹€.
  • λžŒλ‹€μ‹κ³Ό ν•¨κ»˜ μ‚¬μš©ν•  수 μžˆλŠ” ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€μž„μ„ λͺ…μ‹œν•©λ‹ˆλ‹€.

βœ”οΈ Introspection - Reflection

βœ… λ¦¬ν”Œλ ‰μ…˜μ΄λž€?

  • 컴파일 이후 μ‹€ν–‰ 쀑에 클래슀의 ν•„λ“œλ‚˜ λ©”μ„œλ“œλ₯Ό μ‘°μ‚¬ν•˜κ³  μ‘°μž‘ν•  수 μžˆλŠ” κΈ°λŠ₯μž…λ‹ˆλ‹€.
  • 객체의 λŸ°νƒ€μž„ 정보λ₯Ό ν™œμš©ν•΄ λ™μ μœΌλ‘œ μ½”λ“œλ₯Ό μ‹€ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

ℹ️ Introspection의 사전적 의미 : μžμ•„μ„±μ°° λ˜λŠ” μžκΈ°λ°˜μ„±. classλ₯Ό Introspectν•œλ‹€λŠ” μ˜λ―ΈλŠ” class의 ꡬ쑰λ₯Ό νŒŒμ•…ν•΄ properties, methods 와 eventsλ₯Ό νŒŒμ•…ν•¨μ„ μ˜λ―Έν•©λ‹ˆλ‹€.


✏️ 퍼블릭 λ©”μ„œλ“œ μ‹€ν–‰ μ‹€μŠ΅

import java.lang.reflect.Field;
import java.lang.reflect.Method;

// ⭐메타 정보λ₯Ό κ°€μ Έμ˜¬ ν…ŒμŠ€νŠΈ 클래슀 생성
class ReflectionDemo {
    public  String noSecret = "μ•ˆλΉ„λ°€μž…λ‹ˆλ‹€.";
    private String secret = "λΉ„λ°€μž…λ‹ˆλ‹€.";

    public ReflectionDemo() {
        System.out.println("ReflectionDemo μƒμ„±μž μ‹€ν–‰");
    }

    public String greet(String name) {
        return "Hello, " + name;
    }

    private String reveal(String code) {
        return "Access granted to: " + code;
    }
}

public class Main {
    public static void main(String[] args) {
    	// ⭐Class instance둜 ν•΄λ‹Ή 클래슀의 class 객체 μ–»μ–΄μ˜€κΈ°
        Class<?> clazz = ReflectionDemo.class;

		// ⭐ .getName()으둜 ν•΄λ‹Ή 클래슀의 전체 이름 (νŒ¨ν‚€μ§€κ²½λ‘œ 포함) ν™•μΈν•˜κΈ°
        System.out.println("클래슀 이름: " + clazz.getName());

		// ⭐ .getDeclaredFields()둜 ν•΄λ‹Ή 클래슀의 λͺ¨λ“  ν•„λ“œ Field[] λ°°μ—΄λ‘œ κ°€μ Έμ˜€κΈ°
        // import java.lang.reflect.Field; μΆ”κ°€
        System.out.println("\n[ν•„λ“œ λͺ©λ‘]");
        Field[] fields = clazz.getDeclaredFields();
        for(Field field: fields) {
            System.out.println("ν•„λ“œ: " + field.getName());
        }

		// ⭐ .getDeclaredMethods()둜 ν•΄λ‹Ή 클래슀의 λͺ¨λ“  λ©”μ†Œλ“œ Method[] λ°°μ—΄λ‘œ κ°€μ Έμ˜€κΈ°
        // import java.lang.reflect.Method; μΆ”κ°€
        System.out.println("\n[λ©”μ„œλ“œ λͺ©λ‘]");
        Method[] methods = clazz.getDeclaredMethods();
        for(Method method: methods) {
            System.out.print("λ©”μ„œλ“œ: " + method.getName());
            for(Class<?> paramType: method.getParameterTypes()) {
                System.out.println(" νŒŒλΌλ―Έν„° νƒ€μž…: " + paramType.getSimpleName());
            }
        }
		
        try {
        	// ⭐ getDeclaredConstructor().newInstance()둜 μƒμ„±μž ν˜ΈμΆœν•˜μ—¬ μΈμŠ€ν„΄μŠ€ μƒμ„±ν•˜κΈ°
            Object instance = clazz.getDeclaredConstructor().newInstance();
            Method greetMethod = clazz.getDeclaredMethod("greet", String.class);
            Object greetResult = greetMethod.invoke(instance, "j797");
            System.out.println("\n[퍼블릭 λ©”μ„œλ“œ μ‹€ν–‰ κ²°κ³Ό]");
            System.out.println("greet(): " + greetResult);
        } catch (Exception e) {
            e.printStackTrace();;
        }
    }
}
▢️ μ‹€ν–‰ κ²°κ³Ό

[ν•„λ“œ λͺ©λ‘]
ν•„λ“œ: noSecret
ν•„λ“œ: secret

[λ©”μ„œλ“œ λͺ©λ‘]
λ©”μ„œλ“œ: greet νŒŒλΌλ―Έν„° νƒ€μž…: String
λ©”μ„œλ“œ: reveal νŒŒλΌλ―Έν„° νƒ€μž…: String
ReflectionDemo μƒμ„±μž μ‹€ν–‰

[퍼블릭 λ©”μ„œλ“œ μ‹€ν–‰ κ²°κ³Ό]
greet(): Hello, j797

✏️ 프라이빗 λ©”μ„œλ“œ μ‹€ν–‰ 예제

  • Method.invoke(instance, args...)λ₯Ό μ‚¬μš©ν•˜λ©΄ λ¦¬ν”Œλ ‰μ…˜μœΌλ‘œ private λ©”μ„œλ“œλ₯Ό μ‹€ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • 이 방법은 객체의 은닉성(μΊ‘μŠν™”)을 κΉ¨κΈ° λ•Œλ¬Έμ— κΌ­ ν•„μš”ν•œ κ²½μš°μ—λ§Œ μ‹ μ€‘ν•˜κ²Œ μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.
try {
    Object instance = clazz.getDeclaredConstructor().newInstance();
    Method revealMethod = clazz.getDeclaredMethod("reveal", String.class);
    // ⭐private λ©”μ†Œλ“œλ₯Ό getDeclareMethod("methodName", args
    revealMethod.setAccessible(true);
    Object revealResult = revealMethod.invoke(instance, "797");
    System.out.println("reveal(): " + revealResult);
} catch (Exception e) {
    e.printStackTrace();
}

βœ… λ¦¬ν”Œλ ‰μ…˜κ³Ό 객체 μ§€ν–₯

  • λ¦¬ν”Œλ ‰μ…˜μ€ 객체 μ§€ν–₯ 원칙 쀑 μΊ‘μŠν™”(encapsulation) λ₯Ό μœ„λ°˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • private ν•„λ“œμ™€ λ©”μ„œλ“œμ— μ ‘κ·Όν•˜κ³  μ‘°μž‘ν•  수 있기 λ•Œλ¬Έμž…λ‹ˆλ‹€.
  • λ˜ν•œ, 정적 νƒ€μž… μ•ˆμ •μ„±μ„ ν•΄μΉ˜κ³  λŸ°νƒ€μž„ 였λ₯˜ κ°€λŠ₯성을 λ†’μž…λ‹ˆλ‹€.

✏️ μ˜ˆμ‹œ:

  • Class.forName("클래슀λͺ…") β†’ μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” ν΄λž˜μŠ€λŠ” 컴파일 νƒ€μž„μ— 확인 λΆˆκ°€
  • method.invoke() β†’ 잘λͺ»λœ 인자 전달 μ‹œ μ»΄νŒŒμΌλŸ¬κ°€ 였λ₯˜λ₯Ό μž‘μ§€ λͺ»ν•¨

πŸ” λ¦¬ν”Œλ ‰μ…˜μ˜ λ‚¨μš©μ€ μ˜μ‘΄μ„± 증가와 μ½”λ“œ λ‚œλ…ν™”λ₯Ό μ΄ˆλž˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

  • μžλ™μ™„μ„±, λ¦¬νŒ©ν† λ§ λ„κ΅¬μ˜ 도움을 λ°›κΈ° μ–΄λ ΅μŠ΅λ‹ˆλ‹€.
  • μœ μ§€λ³΄μˆ˜μ„±μ΄ λ–¨μ–΄μ§€κ³  ν…ŒμŠ€νŠΈλ„ μ–΄λ €μ›Œμ§ˆ 수 μžˆμŠ΅λ‹ˆλ‹€.

πŸ€” κ·ΈλŸΌμ—λ„ λΆˆκ΅¬ν•˜κ³  λ¦¬ν”Œλ ‰μ…˜μ΄ ν•„μš”ν•œ 이유

  • λ¦¬ν”Œλ ‰μ…˜μ€ ν”„λ ˆμž„μ›Œν¬μ™€ AOP의 핡심 λ„κ΅¬λ‘œ ν™œμš©λ©λ‹ˆλ‹€.

βœ… AOP (Aspect-Oriented Programming)

  • μŠ€ν”„λ§ AOP λ“±μ—μ„œλŠ” λ©”μ„œλ“œ 호좜 전후에 λΆ€κ°€ λ‘œμ§μ„ μ‚½μž…ν•΄μ•Ό ν•©λ‹ˆλ‹€.
  • μ΄λ•Œ λ©”μ„œλ“œλͺ…, νŒŒλΌλ―Έν„°, μ–΄λ…Έν…Œμ΄μ…˜ 등은 λ¦¬ν”Œλ ‰μ…˜μœΌλ‘œ μΆ”μΆœλ©λ‹ˆλ‹€.

βœ… DI (Dependency Injection), ORM λ“±μ—μ„œμ˜ μ–΄λ…Έν…Œμ΄μ…˜ 뢄석

  • @Autowired, @Entity λ“±μ˜ μ–΄λ…Έν…Œμ΄μ…˜μ„ 기반으둜 클래슀 ꡬ쑰λ₯Ό λΆ„μ„ν•˜κ³ 
    객체λ₯Ό λ™μ μœΌλ‘œ μ£Όμž…ν•˜κ±°λ‚˜ λ§€ν•‘ν•©λ‹ˆλ‹€.

βœ… ν”ŒλŸ¬κ·ΈμΈ ꡬ쑰, λŸ°νƒ€μž„ 객체 쑰립 λ“± μœ μ—°ν•œ 섀계에도 유용

  • μ •ν•΄μ§€μ§€ μ•Šμ€ 클래슀λ₯Ό λ™μ μœΌλ‘œ λ‘œλ”©ν•˜κ±°λ‚˜ μ‹€ν–‰ν•΄μ•Ό ν•˜λŠ” 경우 ν•„μˆ˜μ μž…λ‹ˆλ‹€.

πŸ’‘ κ²°λ‘ 

  • 직접 μ‚¬μš©ν•˜λŠ” 것보닀 ν”„λ ˆμž„μ›Œν¬μ— μ˜ν•΄ κ°„μ ‘μ μœΌλ‘œ ν™œμš©λ˜λ„λ‘ μ„€κ³„ν•˜λŠ” 것이 κ°€μž₯ μ΄μƒμ μž…λ‹ˆλ‹€.

πŸ” λ¦¬ν”Œλ ‰μ…˜ μ£Όμš” API μš”μ•½

λ©”μ„œλ“œμ„€λͺ…
getName()클래슀 이름 λ°˜ν™˜
getDeclaredFields()λͺ¨λ“  ν•„λ“œ λ°°μ—΄ λ°˜ν™˜
getDeclaredMethods()λͺ¨λ“  λ©”μ„œλ“œ λ°°μ—΄ λ°˜ν™˜
getDeclaredConstructor()κΈ°λ³Έ μƒμ„±μž λ°˜ν™˜
newInstance()객체 μΈμŠ€ν„΄μŠ€ 생성
setAccessible(true)private 멀버 μ ‘κ·Ό ν—ˆμš©
profile
πŸ—‚οΈ hamstern

0개의 λŒ“κΈ€