Thread

  • 메모리를 할당받아 실행 중인 프로그램을 프로세스라고 한다.
  • 프로세스 내의 명령어 블록으로 시작점과 종료점을 가진다.
  • 실행중에 멈출 수 있으며 동시에 수행 가능하다.
  • 어떠한 프로그램내에서 특히 프로세스 내에서 실행되는 흐름의 단위.

멀티스레딩

여러 스레드를 동시에 실행시키는 응용프로그램을 작성하는 기법.
장점

  • 메모리 공유로 인한 시스템 자원 소모가 줄어든다.
  • 동시에 두가지 이상의 활동을 하는 것이 가능해진다.
    단점
  • 서로 자원을 소모하다가 충돌이 일어날 가능성이 존재
  • 코딩이 난해해져 버그생성확률이 높아진다.

스레드의 생명주기

스레드

  1. Runnable(준비단계)
    스레드가 실행되기 위한 준비단계이다. CPU를 점유하고 있지 않으며, 실행을 하기 위해 대기하고 있는 상태이다. 코딩 상에서 start()메소드를 호출하면 run()메소드에 설정된 스레드가 Runnable상태로 진입한다.

  2. Running(실행상태)
    CPU를 점유하여 실행하고 있는 상태이며, run()메소드는 JVM만이 호출가능하다. Runnable에 있는 여러 스레드 중 우선 순위를 가진 스레드가 결정되면 JVM이 자동으로 run()메소드를 호출하여 스레드가 Running 상태로 진입한다.

  3. Dead(종료상태)
    Runnig상태에서 스레드가 모두 실행되고 난 후 완료 상태입니다. “Done”상태라고도 한다.

  4. Blocked(지연상태)
    CPU점유권을 상실한 상태이다. 후에 특정 메소드를 실행시켜 Runable로 전환한다.
    wait() 메소드에 의해 Blocked 상태가 된 스레드는 nofify() 메소드가 호출되면 Runnable 상태로 간다. sleep(시간) 메소드에 의해 Blocked상태가 된 스레드는 지정된 시간이 지나면 Runnable상태로 간다.

쓰레드 구현과 실행

쓰레드를 구현하는 방법은 두가지가 있다.

  • Thread클래스를 상속
  • Runnable인터페이스를 구현
    Runnable을 사용하는 것이 낫다.
    그 이유는 Thread클래스를 상속받으면 다른 클래스를 상속 받지 못하기 때문이다
    Runnable을 구현하는 방법은 재사용성이 높고 코드의 일관성을 유지 할 수 있다는 장점이 있기 때문에 보다 객체지향적인 방법이라 할 수 있다.

Comment and share

serializable

자바에서 입출력에 사용되는 것은 스트림이라는 데이터 통로를 통해 이동한다.하지만 객체는 바이트형이 아니기 때문에 스트림을 통해 파일에 저장하거나 네트워크로 전송할 수 없다. 따라서 객체를 스트림을 통해 입출력하려면 바이트 배열로 변환하는 것이 필요한데, 이를 직렬화라고 한다. 반대로 스트림을 통해 받은 직렬화된 객체를 원래 모양으로 만드는 과정을 역직렬화라고 한다.
직렬화2

직렬화 조건

  1. 기본형 타입은 직렬화가 가능하다.
  2. Serializable인터페이스를 구현한 객체여야 한다.
  3. transient가 사용된 멤버는 전송되지 않는다.
    transient : Serializable에서 제외시키고 싶을 때 사용하는 keyward.
  4. 생성자나 메소드는 직렬화 대상에 속하지 않는다.

선언해야하는 이유

JVM은 직렬화와 역직렬화를 하는 시점의 클래스에 대한 버전 번호를 부여한다. 만약 그 시점에 클래스의 정의가 바뀌어 있다면 새로운 번호를 할당한다. 그래서 직렬화할 때의 버전 번호와 역직렬화를 할 때의 버전 번호가 다르면 역직렬화가 불가능해 질수도 있다. 이런문제를 해결하기 위해 SerialVersionUID를 사용한다.
간단명료하게 SerialVersionUID값을 저장할 때 클래스 버전이 맞는지 확인하기 위한 용도이다. 만약 직렬화할 때 사용한 SerialVersionUID의 값과 역직렬화 하기 위해 사용했던 SerialVersionUID값이 다르다면 InvalidClassException이 발생할 수 있다.

Comment and share

Exception

예외는 error의 일종이며 프로그램이 수행시 또는 컴파일시에 불능상태를 만들어 버린다. Exception이 방생하는 이유는 여러가지다.
근데 만약 금융시스템 또는 365일 24시간 항상 구동되어야 할 시스템이 Exception으로 인해 시스템이 불능이 되거나 프로그램이 죽어버리게 되면 상당히 곤란할 것이다. 따라서 이를 막기 위해 자바에서는 Exception예외처리라는 방법을 통해 Exception erroe를 처리한다.

종류

컴파일 시점에서 발생하는 예외를 Exception(일반예외)라고 하고,
프로그램 실행시에 발생하는 예외를 RuntimeException(실행예외)라고 한다.
즉, 예외가 발생하는 시점에 프로그램이 실행 전 후 상태에 따라 이를 구분하면 된다.

이 2가지 종류의 Exceoption을 처리하기 위해 자바에서는 java.lang.Exception이라는 최상위 부모 클래스를 제공한다. 따라서 모든 Exception들의 조상을 결국 java.lang.Exception이다.
예외
하늘색 Exceoption들은 단순 Exception이다.(일반예외)
초록색 RuntimeException은 프로그램 실행시 발생하는 런타임 Exception이다.(실행예외)

예외처리 코드 및 실행순서

예외 처리 코드에는 크게 3가지 블록이 존재한다.

  • Try : 실제 코드가 들어가는 곳, 예외 Exception 발생으로 인해 시스템 및 프로그램이 불능상태에 빠지지 않고 시스템 및 프로그램이 정상실행 되도록 유지시켜 준다.
  • Catch : Try블록에서 Exception이 발생하면 코드 실행 순서가 Catch쪽으로 오게 된다. 즉 예외에 대한 후 처리 코드
  • Finally : Try블록에서 Exception과 발생 유무와 상관 없이 무조건 수행되는 코드(옵션이므로 생략 가능)

실행순서

  • Exception 발생!
    Try블록 수행 -> Catch블록 수행 -> Finally블록 수행(생략가능)

  • Exception 미 발생!
    Try블록 수행 -> Finally블록 수행(생략가능)

Comment and share

제네릭

제네릭은 클래스 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법을 의미한다.
제네릭스는 다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스에 컴파일시의 타입체크를 해주는 기능이다.

사용해야 하는 이유

잘못된 타입이 될 수 있는 문제를 컴파일 과정에서 제거할수 있다. 자바 컴파일러는 코드에서 잘못 사용된 타입 때문에 발생하는 문제점을 제거하기 위해 제네릭 코드에 대한 강한 타입 체크를 한다.
실행 시 타입에러가 나는 것보다는 컴파일 시에 미리 타입을 강하게 체크해서 에러를 사전에 방지하는 것이 좋다. 또 제네릭 코드를 사용하면 타입을 국한하기 때문에 요소를 찾아올 때 타입 변환을 할 필요가 없어 프로그램 성능이 향상되는 효과를 얻을 수 있다.
예시

ArrayList list = new ArrayList(); //제네릭을 사용하지 않을경우
list.add("test");
String temp = (String) list.get(0); //타입변환이 필요함
        
ArrayList<String> list2 = new ArrayList(); //제네릭을 사용할 경우
list2.add("test");
temp = list2.get(0); //타입변환이 필요없음

사용법

제네릭 타입은 타입을 파라미터로 가지는 클래스와 인터페이스이다. 제네릭 타입은 클래스 또는 인터페이스 이름 뒤에 < >를 쓰고 사이에 타입 파라미터가 위치한다.

public class 클래스명<T> {...}
public interface 인터페이스명<T> {...}

타입인자

타입인자 설명
T Type
E Element
K Key
N Number
V Value
R Result

Comment and share

ListIterator

ListIterator인터페이스는 Iterator인터페이스를 상속받아 여러 기능을 추가한 인터페이스이다.
Iterator인터페이스는 컬렉션의 요소에 접근할 때 한 방향으로만 이동할 수 있다.
Listiterator 인터페이스는 컬렉션 요소의 대체, 추가 그리고 인덱스 검색 등을 위한 작업에서 양방향으로 이동하는 것을 지원한다.
단, Listeriterator인터페이스는 List인터페이스를 구현한 List컬렉션 클래스에서만 Listiterator()메소드를 통해 사용할 수 있다.
예제

LinkedList<Integer> lnkList = new LinkedList<Integer>();

lnkList.add(4);
lnkList.add(2);
lnkList.add(3);
lnkList.add(1);

ListIterator<Integer> iter = lnkList.listIterator();
while (iter.hasNext()) {
    System.out.print(iter.next() + " ");
}

while (iter.hasPrevious()) {
    System.out.print(iter.previous() + " ");
}

결과값

4 3 2 1
1 3 2 4

Comment and share

오름차순 정렬

Arrays.sort()메서드의 매개값으로 기본 타입 배열이나 String배열을 지정해주면 자동으로 오름차순 정렬이 된다.
예제

import java.util.Arrays;

public class Sort{
    public static void main(String[] args)  {
        int arr[] = {4,23,33,15,17,19};
        Arrays.sort(arr);
        
        for (int i : arr) {
            System.out.print("["+i+"]");
        }
    }
}

결과값

[4][15][17][19][23][33]

내림차순 정렬

배열을 내림차순으로 정렬할 때는 Collections 클래스의 reverseOrder() 함수를 사용하면 된다. 만약 기본 타입 배열을 내림차순으로 정렬하고 싶다면 기본 타입의 배열을 래퍼클래스로 만들어 Comparator를 두번째 인자에 넣어주어야 역순으로 정렬할 수 있다.

import java.util.Arrays;

public class Sort{
    public static void main(String[] args)  {
        Integer arr[] = {4,23,33,15,17,19};
        Arrays.sort(arr,Collections.reverseOrder());
        
        for (int i : arr) {
            System.out.print("["+i+"]");
        }
    }
}

결과값

[33][23][19][17][15][4]

배열 일부분만 정렬

Arrays.sort()메서드의 매개값으로 배열, 시작 index, 끝 index를 넣어주면 일부분만 정렬할 수 있다.

import java.util.Arrays;

public class Main{
public static void main(String[] args)  {
        int arr[] = {4,23,33,15,17,19};

        Arrays.sort(arr, 0, 4); // 0,1,2,3 요소만 정렬
        
        for (int i : arr) {
            System.out.print("["+i+"]");
        }
    }
}

결과값

[4][15][23][33][17][19]

Comment and share

Stack과 Queue

Stack은 LIFO(Last in first out) Queue는 FIFO(First in first out)으로 되어있다.

Stack의 메서드

메서드 설명
boolean empty( ) Stack 이 비어있는지 알려줌
Object peek( ) Stack 의 맨 위에 저장된 객체를 반환pop( ) 과 달리 Stack 에서 객체를 꺼내지 않음(비었을 때는 EmptyStackException 발생)
Object pop( ) Stack 의 맨 위에 저장된 객체를 꺼냄(비었을 때는 EmptyStackException 발생)
Object push(Object item) Stack 에 객체( item )를 저장
int search(Object o) Stack 에서 주어진 객체( o )를 찾아서 그 위치를 반환, 못 찾으면 -1 을 반환(배열과 달리 위치가 1부터 시작)

Queue의 메서드

메서드 설 명
boolean add(Object o) 지정된 객체를 Queue 에 추가 성공하면 true를 반환, 저장공간이 부족하면 IllegalStateException 발생
Object remove( ) Queue 에서 객체를 꺼내 반환. 비어있으면 NoSuchElementException 발생
Object element( ) 삭제없이 요소를 읽어옴 peek 와 달리 Queue 가 비었을때 NoSuchElementException 발생
boolean offer(Object o) Queue 에 객체를 저장 성공하면 true, 실패하면 false를 반환
Object poll( ) Queue 에서 객체를 꺼내서 반환. 비어있으면 null을 반환
Object peek( ) 삭제없이 요소를 읽어온다. Queue가 비어있으면 null을 반환
예제
package Example;

import java.util.*;

public class Example {
    public static void main(String[] args) {
        Stack st = new Stack();
        Queue q = new LinkedList();    //Queue의 인터페이스 구현체인 LinkedList를 사용
        
        st.push("0");
        st.push("1");
        st.push("2");
        
        q.offer("0");
        q.offer("1");
        q.offer("2");
        
        System.out.println("=== Stack ===");
        while(!st.isEmpty()) {
            System.out.println(st.pop());
        }
        
        System.out.println("=== Queue ===");
        while(!q.isEmpty()) {
            System.out.println(q.poll());
        }
    }
}

결과값

===Stack===
2
1
0
===Queue===
0
1
2

자베에서는 스택을 Stack클래스로 구현하여 제공하지만 큐는 Queue인터페이스만 있고 별도의 클래스가 없다. 그래서 Queue인터페이스를 구현한 클래스들을 사용해야 한다.

Comment and share

HashMap

  • Map의 일종으로 key와 value의 쌍으로 이루어진 데이터를 보관한다.
  • null key와 null value를 모두 허용한다.
  • 내부적을 데이터에 접근할 때 동기화를 보장하지 않는다.
  • 데이터의 순서를 보장하지 않는다.
  • 중복된 key값을 허용하진 않지만, 중복된 값은 가질 수 있다.

Comment and share

hashtable

hashtable은 Map을 상속받아 key,value 형태를 가지게 된다.
key,value는 한쌍으로 사용되며 key로 식별용 값, value는 사용할 값을 넣는 식이다.

HashMap과 상당히 비슷한데 완전 똑같은 것은 아니므로 비교해 보자면

  1. HashTable은 동기화가 되어 있으나, HashMap은 동기화 되어있지 않다.

  2. HashTable은 key, value에 null값을 허용하지 않지만 HashMap은 허용한다.

     Hashtable 안에 값 넣기
     Hashtable.put(key, value);
    
     Hashtable 안의 값 가져오기
     Hashtable.get(key);
    
     Hashtable 안의 값 바꾸기
     Hashtable.replace(key, value);
    
     Hashtable 안의 내용 삭제하기
     Hashtable.remove(key);
    
     Hashtable의 크기 0인지 확인하기
     Hashtable.isEmpty();
     
     Hashtable 사이즈 확인하기
     Hashtable.size();
     
     Hashtable 안에 특정 Key, Value 들었는지 확인하기
     Hashtable.containsKey(key);
     Hashtable.containsValue(value);
    
     Hashtable 안에 들어있는 전체 Key 확인하기
     Hashtable.keySet();
     import java.util.Hashtable;
    

예제

public class HashTableExample {

    public static void main(String[] args) {
        Hashtable<Integer, String> ht = new Hashtable<Integer, String>();
        ht.put(0, "철수");
        ht.put(1, "영희");
        ht.put(2, "영수"); // Hashtable에 값 삽입
        ht.replace(2, "수철"); // Hashtable 값 바꾸기
        ht.remove(2); // Hashtable 값 삭제

        for(int i = 0; i<ht.size(); i++) {
            System.out.println(ht.get(i)); // Hashtable 값 출력
        }
        
        System.out.println("Hashtable 크기 : " + ht.size());
        System.out.println("Hashtable key 확인 : " + ht.containsKey(2));
        System.out.println("Hashtable value 확인 : " + ht.containsValue("수철"));
        System.out.println("Hashtable 크기 0인지 확인 : " + ht.isEmpty());
        System.out.println("Hashtable 전체 Key 확인 : " + ht.keySet());
        
    }

}
결과값
철수
영희
Hashtable 크기 : 2
Hashtable key 확인 : false
Hashtable value 확인 : false
Hashtable 크기 0인지 확인 : false
Hashtable 전체 key 확인 : [1, 0]    

Comment and share

new 연산자

클래스 객체변수 = new 클래스();

인스턴스를 생성할 때 사용하는 코드이며 객체 변수가 실제 데이터가 아닌 참조 값을 갖는다는 내용이 포함되어 있다.
new는 클래스 타입의 인스턴스를 생성해주는 역할을 담당한다.
new연산자를 통해 메모리(Heap 영역)에 데이터를 저장할 공간을 할당받고 그 공간의 참조값을 객체에게 반환하여 주고 이어서 생성자를 호출하게 된다. 인스턴스를 핸들하기 위해서는 new 연산자를 통해 참조값을 저장한 객체로만 접근이 가능하다.

클래스      객체변수    =    new        클래스();
자료형      참조값저장     메모리할당   생성자호출

Comment and share

Hyeon Soo Ahn

author.bio


author.job