Back_End/Java
Thread 와 Collection
BaekSJ
2024. 4. 22. 16:44
Java Thread개요
💡Thread 란 무엇인가?
스레드는 프로그램 내 실행 경로인 경량 프로세스이다. Java는 스레드를 사용하여 코드의 병렬 실행을 가능하게 한다. 각 Java 애플리케이션에는 최소한 하나의 스레드(애플리케이션이 시작될 때 실행되는 메인 스레드)가 있다. 다른 작업을 동시에 수행하기 위해 추가 스레드를 생성할 수 있다.
스레드 생성 및 사용
1. 스레드 생성 방법:
- Thread 클래스에서 상속: 이 접근 방식에는 Thread를 확장하는 새 클래스를 생성하고 스레드가 실행할 코드를 정의하는 run() 메서드를 재정의하는 작업이 포함된다.
- Runnable 인터페이스 구현: 이 접근 방식에는 run() 메서드를 정의하여 Runnable 인터페이스를 구현하는 작업이 포함된다. 그런 다음 Thread 객체가 생성되어 Runnable 객체를 생성자에 전달한다.
2. 중요 구성 요소:
- run() 메서드: 이 메서드는 스레드의 작업이 발생하는 곳이다. run() 내부의 코드는 스레드가 실행될 때 수행할 작업을 지정한다.
- start() 메서드: 이 메서드는 스레드 실행을 시작하기 위해 Thread 개체에서 호출된다. 이는 JVM이 별도의 호출 스택에서 스레드의 'run()' 메서드를 호출하도록 한다.
3. 스레드 수명주기 관리:
- join() 메서드: 이 메서드는 조인된 스레드가 작업을 완료할 때까지 현재 스레드(일반적으로 메인 스레드)의 실행을 일시 중지하려고 할 때 사용된다. 이 메서드는 InterruptedException을 발생시키므로 try-catch 블록으로 묶거나 메서드 시그니처에 예외를 선언해야 한다.
4. 스레드 이름 지정:
- 스레드 이름 지정: 스레드에 의미 있는 이름을 지정하는 것은 디버깅 목적에 도움이 될 수 있다. 이는 Thread 클래스의 생성자를 통해 또는 setName() 메소드를 사용하여 수행할 수 있다.
- 스레드 이름 검색: getName() 메서드를 사용하여 스레드 이름을 가져올 수 있습니다.
📢Java의 스레드 예
// Thread 클래스를 확장하는 방법
class MyThread extends Thread {
public MyThread(String name) {
super(name); // 스레드 클래스 생성자를 통해 스레드 이름 설정
}
@Override
public void run() {
System.out.println("스레드 실행 중: " + getName());
}
}
// Runnable 인터페이스를 구현하는 방법
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Runnable 실행 중");
}
}
public class ThreadExample {
public static void main(String[] args) {
MyThread t1 = new MyThread("스레드-1");
t1.start();
Thread t2 = new Thread(new MyRunnable(), "Runnable-1");
t2.start();
try {
t1.join(); // t1가 끝날 때까지 기다림
t2.join(); // t2가 끝날 때까지 기다림
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Main thread finished.");
}
}
Java Collection 프레임워크 개요
💡컬렉션 프레임워크란 무엇인가?
Java 컬렉션 프레임워크는 데이터 그룹을 객체로 저장하고 조작하기 위한 인터페이스 및 클래스 세트를 제공한다. 프레임워크에는 목록, 맵 및 세트로 광범위하게 분류할 수 있는 여러 가지 유형의 컬렉션이 포함되어 있다.
1. List 시리즈
Java의 List는 요소를 순서대로 유지하여 위치 액세스 및 삽입을 허용하는 정렬된 컬렉션이다. 목록의 요소는 색인 번호를 통해 액세스할 수 있다.
배열목록:
- ArrayList는 크기 조정 가능한 배열을 기반으로 하는 List 인터페이스의 구현이다. 이는 요소에 일정한 시간에 액세스할 수 있으므로 목록 요소에 자주 액세스해야 하는 시나리오에 탁월하다.
- ArrayList에서 요소가 제거되면 공백을 메우기 위해 모든 후속 요소가 이동되며, 특히 목록의 시작이나 중간에서 제거가 자주 발생하는 경우 제거 비용이 많이 들 수 있다.
링크된 목록:
- ArrayList와 달리 LinkedList는 이중 연결 리스트로 구현된다. 목록의 각 요소(노드)에는 다음 요소와 이전 요소를 연결하는 두 개의 참조(링크)가 포함되어 있다.
- LinkedList는 단순히 링크를 조정하여 목록에서 상수 시간 삽입 및 제거를 허용하므로 요소 이동으로 인한 오버헤드를 방지한다. 그러나 LinkedList의 요소에 액세스하려면 시작이나 끝(둘 중 더 가까운 것)부터 순차적인 순회가 필요하므로 임의 액세스가 느려진다.
2. Map 시리즈
각 키가 고유한 키-값 쌍으로 저장소 요소를 매핑한다. 맵은 요소의 순서를 유지하지 않는다.
- 키 및 값:
- 맵의 각 요소는 키-값 쌍으로, 키는 항목을 고유하게 식별하고 값은 키와 연결된 데이터이다.
- 맵의 액세스, 삽입 및 제거 작업은 일반적으로 키의 해싱 알고리즘 효율성에 따라 달라진다.
3. Set 시리즈
세트는 고유한 요소만 저장하는 컬렉션이다. 요소의 쌍이나 시퀀스를 저장하지 않으며 목록과 같은 위치 액세스 개념도 없다.
- 독창성:
- 세트의 모든 요소는 equals 및 hashCode 메소드에 의해 정의된 기준에 따라 고유해야 한다.
- 목록과 마찬가지로 다양한 집합 구현(예: HashSet, LinkedHashSet 또는 TreeSet)의 성능 특성은 다양할 수 있다.
비교 및 사용 사례
ArrayList 대 LinkedList:
- ArrayList는 일반적으로 O(1) 임의 액세스 성능으로 인해 가져오기/설정 작업이 더 많은 경우 선호된다.
- LinkedList는 삽입과 삭제가 자주 발생하고 성능이 중요한 목록, 특히 목록 끝 부분에 유리하다. 이러한 작업은 일반적으로 O(1)이기 때문이다.
Java 컬렉션 프레임워크의 이러한 구조를 통해 개발자는 성능 특성 및 가장 자주 수행할 것으로 예상되는 작업 유형과 관련된 특정 요구 사항을 기반으로 적절한 컬렉션 유형을 선택할 수 있다!