1.1 스레드(Thread)
- 하나의 프로세스 내부에서 독립적으로 실행되는 하나의 작업 단위.
- ex) 작업 관리자에 실행되는 프로세스들
- 모든 프로세스에는 최소 하나 이상의 스레드가 존재하며(main()),
두 개 이상의 스레드를 가지면 멀티 스레드라고 한다.
- 멀티 스레드(main() 이외의 다른 스레드)를 구현 하려면 Thread 클래스를
상속하거나 Runnable 인터페이스를 구현해야 한다.
- 멀티 스레드 작업 시 각 스레드끼리 정보를 주고 받을 수 있다.
- 프로세스끼리는 정보를 주고 받을 수 없다.
1.2 스레드 생성
- 방법
1) Thread 클래스를 상속 받아 객체 생성
2) Runnable 인터페이스 구현 (주로 많이 사용)
* Thread 클래스를 상속받으면 다른 클래스를 상속받을 수 없기 때문에
Runnable 인터페이스를 구현하는것이 일반적이다.
1.3 스레드 생성 주기
Start() Run()
스레드 객체 생성(new) → 실행 대기(Runnable) → 실행(Running) → 종료(Dead)
↑ ↓
↖ ↙
중단(Blocked)
- Runnable 상태 : 스레드가 실행되기 전 준비 단계
- Running 상태 : 선택된 스레드가 실행되는 단계
- Blocked 상태 : 스레드가 작업을 완수하지 못하고 작업을 일시 중단하는 단계
1.1 제네릭(Generic)
- Java5부터 새로 추가된 타입으로 제네릭을 이용함으로써
잘못된 타입이 사용될 수 있는 문제를 컴파일 과정에서 제거할 수 있다.
- 컬렉션 등에서 널리 사용되므로 확실히 이해해 두어야 한다.
- 클래스나 메소드에서 컴파일 할 때 타입체크(Type check)를 하는 기능이다.
1.2 제네릭의 이점
- 컴파일 시 강한 타입 체크를 할 수 있다.
클래스나 메소드에서 컴파일 할 때 타입체크(Type check)를 하여
실행 에러가 나기 전 컴파일 단계에서 에러를 사전에 방지한다.
- 미리 객체(인스턴스)의 공통적인 타입을 명시해서 처리하기 때문에 안정성이 높고, 타입 변환(casting)을 제거한다.
ex)
<비제네릭 코드>
List list = new ArrayList();
list.add("hello");
String str = (String)list.get(0); // 타입 변환을 해야 한다.
↓
<제네릭 코드>
List<String> list = new ArrayList<String>();
list.add("hello");
String str = list.get(0); // 타입 변환을 하지 않는다.
- 제네릭 클래스와 제네릭 메소드의 구현이 가능하다.
- 2개 이상의 제네릭 타입 선언이 가능하다.
- 주의사항
1) T obj = new T(); 불가능! (T의 크기를 알 수 없기 때문에)
2) T[] arr = new T[3]; 불가능! (T의 크기를 알 수 없기 때문에)
3) T[] arr; 가능!
class Box <T> {
private T obj;
public void setObj(T obj) {
this.obj = obj;
}
public T getObj() {
return obj;
}
}
// main
Box<String> box = new Box<>(); // 구체화 : T가 무엇인지 알려주는 것
Box<String> box = new Box<String>(); (위와 동일한내용) // 구체화는 referenceType 만 가능 하다. (PrimitiveType은 불가!!)
// 컴파일 시점
T <- String
class Box { // 컴파일 시점에 구체화 된 클래스
private String obj;
public void setObj(String obj) {
this.obj = obj;
}
public String getObj() {
return obj;
}
}
1.1 컬렉션 프레임워크 (Collection Framework)
- 데이터를 다루기 위한 표준화된 구조 (모든 프레임 워크는 제네릭타입이 자동으로 들어가 있다.)
- 핵심 구조
Collection ─┬── List ──────┬── ArrayList
│ ├── LinkedList
│ └── Vector
│
└── Set ────────── HashSet
Map ───────────────────────┬── HashMap
├── SortedMap ─── TreeMap
└── HashTable
1.2 주요 인터페이스 분류
- List
1) 순서가 있는 데이터의 집합
2) 중복 저장 허용
- Set
1) 순서가 없는 데이터의 집합
2) 중복 저장 불가
- Map
1) 키(key)와 값(value)의 쌍(pair)으로 이루어진 데이터
2) 순서가 없는 데이터의 집합
3) 키(key)는 중복 저장 불가
4) 값(value)는 중복 저장 허용
- 반복자 (Iterator)를 사용 할 수 있다.
1) Iterator 메소드
(1) hasNext() : 다음 요소에 읽어 올 요소가 있는지 확인하는 메소드
있으면 true 없으면 false 반환.
(2) next() : 다음 요소를 가져온다.
(3) remove() : next()로 읽어온 요소를 삭제한다.
List<String> list = new ArrayList<>();
Iterator itr = list.iterator(); // itr : 컬렉션의 요소를 꺼낼 수 있다.
while(itr.hasNext()){
itr.next();
}
1.3 구현 클래스
<List>
- ArrayList
1. 객체(인스턴스)를 여러 개 저장 할 수 있는 '배열'을 구현한 컬렉션이다.
2. 가장 많이 사용하는 컬렉션이다.
3. 기존엔 Vector를 많이 사용했다.(Vector는 ArrayList와 내부 구조가 같지만 멀티 스레드 지원x)
4. 장점
1) 구조가 단순하다.
2) 읽어 들이는 속도가 빠르다.(순차적일때)
3) 저장된 객체의 변화가 적은 경우에 사용하는 것이 좋다. (이미 저장된 것은 변화가 적다.)
5. 단점
1) 일단 만들고 나면 나중에 크기 변경이 어렵다.
2) 처음부터 크게만들면 공간 낭비가 생긴다.
3) 비순차적 접근이 느리다.
4) 데이터의 중간 위치에 추가/제거가 어렵다. (<-> LinkedList : 추가/제거가 쉽다.)
- LinkedList
1. ArrayList와 사용방법은 같지만 내부 구조가 다르다.
1. 자신과 연결된 다음 요소에 대한 참조(다음데이터의 위치) + 데이터로 구성된다.
2. 비연속적인 공간을 사용한다.
3. 장점
1) 추가/제거 작업이 빠르다.
2) 잦은 추가/제거가 발생되는 경우에 사용한다.
4. 단점
1) 순차적인 순회가 느리다.
2) 구현이 어렵고, 오류가 발생 할 가능성이 있다.
<Set>
- HashSet
1. Set 인터페이스를 구현한 대표적인 클래스이다.
2. 중복된 데이터는 저장되지 않는다.
3. 중복된 데이터 판단 원리
1) hashCode() 확인
(1) 값이 같으면 equals() 호출해서 동등비교
(2) 값이 다르면 다른 데이터로 판단
2) equals() 확인 (값이 같을때)
4. 사용자가 정의한 객체(인스턴스)를 저장하려면 hashCode(), equals() 를 오버라이드 해야한다.
5. 저장 순서가 없다. (add 한 순서대로 유지되지 않는다.)
6. add 한 순서를 유지하려면 LinkedHashSet클래스를 사용한다.
- TreeSet
1. 이진탐색트리(BinarySearchTree)의 형태로 데이터를 저장.
2. 데이터의 추가/삭제 시간이 걸리지만 검색과 정렬이 뛰어난 장점
3. 중복된 데이터는 저장되지 않는다.
<Map>
- HashMap
1. 해시코드를 사용하는 Map 이다.(많은 양의 자료에 적합하다.)
2. 키(key)와 값(value)의 조합으로 데이터를 저장한다.
3. 키는 중복 저장될 수 없지만 값은 중복 저장될 수 있다.
4. 기존 저장된 키와 동일한 키로 값을 저장하면 새로운 값을 덮어쓴다.
5. HashTable과 동일한 구조를 가지고 있지만 멀티스레드로 동시에 실행할 수 없다.
반응형