[3주차] 컬렉션, 스레드

goodstar·2024년 11월 12일
0

Java 스터디

목록 보기
9/14
post-thumbnail

1. Map 인터페이스는 왜 Collection 인터페이스에 상속을 받지 않았나?

MapCollection과 데이터 구조의 성격이 다르기 때문에 상속되지 않았습니다.

Collection 인터페이스는 단일 요소의 집합을 다루지만, Map은 키와 값의 쌍을 다루는 구조입니다. 따라서 add, remove와 같은 Collection의 메서드가 Map에는 적합하지 않습니다.

Set, List 등은 각각의 요소만 저장하지만, Mapput(key, value)처럼 두 개의 요소를 함께 저장합니다.

2. IterableIterator의 차이는?

Iterablefor-each와 같은 반복이 가능함을 나타내는 인터페이스이며, Iterator는 실제 반복을 수행하는 객체입니다.

Iterable을 구현한 클래스는 iterator() 메서드를 통해 Iterator를 반환해 순회할 수 있게 합니다.
IteratorhasNext()next() 메서드로 컬렉션을 순회합니다.

// 1. Iterable을 사용하여 for-each문으로 반복
        System.out.println("Using for-each loop:");
        for (String item : list) {  // 내부적으로 list.iterator()가 호출됩니다.
            System.out.println(item);
        }

// 2. Iterator를 사용하여 반복
        System.out.println("\nUsing Iterator directly:");
        Iterator<String> iterator = list.iterator(); // iterator() 메서드를 호출하여 Iterator 객체를 얻습니다.
        while (iterator.hasNext()) {  // hasNext()를 통해 다음 요소가 있는지 확인합니다.
            String item = iterator.next();  // next()로 다음 요소를 가져옵니다.
            System.out.println(item);
        }

1번처럼 작성을 하여도, 컴파일러가 2번으로 변환시켜 작동하기에 결국 2번코드가 실행된다.

3. CollectionCollections의 차이는?

Collection은 인터페이스이며, Collections는 컬렉션과 관련된 유틸리티 클래스입니다.

Collection 인터페이스는 데이터 요소 집합을 다루는 여러 인터페이스(List, Set, Queue)의 상위 인터페이스입니다.
반면 Collections 클래스는 정렬, 검색, 채우기와 같은 작업을 제공하는 유틸리티 메서드를 포함합니다.

        List<String> fruits = new ArrayList<>();
        fruits.add("Orange");
        fruits.add("Apple");
        fruits.add("Banana");

        System.out.println("정렬 전: " + fruits); // 출력: 정렬 전: [Orange, Apple, Banana]
        Collections.sort(fruits); // 오름차순 정렬
        System.out.println("정렬 후: " + fruits); // 출력: 정렬 후: [Apple, Banana, Orange]
        
        Collections.shuffle(fruits); // 리스트 요소 랜덤 섞기
        System.out.println("정렬 후: " + fruits); // 출력: 정렬 후: [Banana, Apple, Orange] (랜덤 결과)
        
        

스레드

1. Java에서 스레드를 만드는 방법.

스레드는 Thread 클래스를 상속하거나 Runnable 인터페이스를 구현하여 생성합니다.

Thread 클래스를 상속받으면 run 메서드를 재정의하여 스레드의 작업을 정의할 수 있고, Runnable을 구현하는 방식은 다중 상속을 지원하지 않는 자바에서 더 권장됩니다.

    class MyThread extends Thread {
        public void run() {
            System.out.println("Thread 실행");
        }
    }
    new MyThread().start();
    
    class MyRunnable implements Runnable {
        public void run() {
            System.out.println("Runnable 실행");
        }
    }
    new Thread(new MyRunnable()).start();

2. 스레드 풀이란 무엇이고, 왜 사용할까요?

스레드 풀은 일정 수의 스레드를 미리 생성해 두고, 작업 요청이 들어올 때마다 스레드 풀에서 스레드를 할당하여 작업을 처리하는 기법이다.

스레드 풀은 자주 생성되고 제거되는 스레드에 대한 부하를 줄이며, 제한된 수의 스레드로 자원 낭비를 방지합니다. 특히 서버나 멀티스레드 애플리케이션에서 효율적입니다.

ExecutorService를 통해 스레드 풀을 생성하고, 여러 작업을 스레드 풀에 할당해 효율적으로 실행할 수 있습니다.

    ExecutorService executor = Executors.newFixedThreadPool(5);
    executor.submit(() -> System.out.println("작업 실행"));

권장 설정: 스레드 수 = CPU 코어 수 (1 + (I/O대기시간/전체작업시간) )
ex) 4코어 CPU와 50%의 I/O 대기 시간이 있는 경우, 스레드 수는 4
(1 + 0.5) = 6


3. 스프링과 같은 프레임워크에서는 스레드 풀의 스레드 개수를 수백 개 이상으로 운영하는 이유는?

많은 요청을 동시에 처리하기 위해 Context Switching이 발생함에도 Context Switching의 비용보다 다수의 스레드를 운영하는 이점이 크기 때문입니다.

웹 애플리케이션 서버는 수많은 사용자가 동시에 접근하고, 빈번하게 네트워크, 파일 입출력과 같은 작업을 처리해야하므로 많은 스레드가 필요합니다. 각 요청을 빠르게 처리하지 않으면 대기 시간이 길어지기 때문에, Context Switching으로 인한 성능 저하를 감수하고도 높은 수의 스레드를 사용하는 것이 더 효율적입니다.

I/O 바운드 작업(예: 데이터베이스 접근, 파일 입출력, 네트워크 통신)의 경우 스레드가 대기 상태일 때 다른 작업을 처리할 수 있도록 많은 스레드를 사용해 동시성을 높이는 것이 더 효율적입니다.

Context Switching이란?
운영 체제에서 CPU가 현재 실행 중인 프로세스나 스레드를 중지하고, 다른 프로세스나 스레드를 실행하기 위해 필요한 상태를 저장하고 불러오는 과정입니다. 즉, CPU가 여러 작업을 동시에 처리하는 것처럼 보이도록 하기 위해 빠르게 프로세스를 전환하는 작업입니다.

0개의 댓글

관련 채용 정보