보조 스트림 

  • 다른 스트림과 연결이 되어 여러 가지 편리한 기능을 제공해주는 스트림
  • 자체적으로 입출력을 수행할 수 없기 때문에 입출력 소스와 바로 연결되는 InputStream, OutputStream, Reader, Writer 등에  연결해서 입출력을 수행한다.
  • 문자 변환, 입출력 성능 햐상, 기본 타입 입출력 등의 기능을 제공한다.

https://hudi.blog/java-filter-stream/

 

문자 변환

  • 소스 스트림이 바이트 기반 스트림(InputStream, OutputStream, FileInputStream, FileOutputStream)이면서 입출력 데이터가 문자라면 Reader와 Writer로 변환해서 사용하는 것을 고려할 수 있다.
  • 그 이유는 문자 입출력은 Reader와 Writer가 편리하기 때문
  • OutputStreamWriter는 Writer로 변환하는 보조 스트림이고, InputStreamReader는 Reader로 변환하는 보조 스트림이다.

 

성능 향상

  • 기본적으로 출력 스트림은 내부에 작은 버퍼를 가지고 있다. 하지만 이것만으로는 불충분하다.
  • 보조 스트림 중에서는 메모리 버퍼를 추가로 제공하여 프로그램의 실행 성능을 향상시키는 것들이 있다.
  • 바이트 기반 스트림에서느 BufferedInputStream, BuffuredOutputStream이 있고 문자 기반 스트림에는 BuffuerdReader, BuffuredWriter가 있다.

 

기본 타입 입출력 

  • DataInputStream과 DataOutputStream 보조  스트림을 연결하면 기본타입인 boolean, char, short, int, long, float, double을 입출력할 수 있다.

개행 출력

  • PrintStream/PrintWriter의 pringln() 메소드는 출력할 데이터 끝에 개행 문자인 '\n'을 추가한다.
  • 그래서 출력 시 콘솔이나 파일에서 줄 바꿈이 일어난다.

'Coding > Java' 카테고리의 다른 글

[32] JAVA 입출력 스트림  (0) 2022.12.28
[31] JAVA LIFO와 FIFO 컬렉션  (0) 2022.12.25
[30] JAVA 컬렉션 프레임워크  (0) 2022.12.25
[29] JAVA 스레드 제어  (0) 2022.12.21
[28] JAVA 멀티스레드  (0) 2022.12.21

스트림이란?

자바에서 데이터는 스트림(Stream)을 통해 입출력 된다.

스트림이란 단일 방향으로 연속적으로 흘러가는 것을 의미하는데, 데이터가 출발지에서 도착지로 흘러가는 것을 의미한다.

  • 입력 스트림(InputStream) : 프로그램으로 데이터를 읽어드리는 스트림. 프로그램이 도착지인 경우 사용
  • 출력 스트림(OutputStream) : 프로그램으로 데이터를 내보내내는 스트림. 프로그램이 출발지인 경우 사용

 

https://kerpect.tistory.com/52

 

입출력 스트림의 종류

  • 바이트(Byte)기반 스트림: 그림, 멀티미디어 등의 바이너리 데이터를 읽고 출력할 때 사용
  • 문자(Character)기반 스트림: 문지 데이터를 읽고 출력할 때 사용
구분 바이트 기반 스트림 문자기반 스트림
입력 스트림 출력 스트림 입력 스트림 출력 스트림
최상위 클래스 InPutStream OutputStream Reader Writer
하위 클래스(예) XXXInPutStream
( FileInPutStream )
XXXOutputStream
( FileOutputStream )
XXXReader
( FileReader )
XXXWriter
( FileWriter )

 

바이트 출력 스트림 : OutputStream

  • OutputStream은 바이트 기반 출력 스트림의 최상위 클래스로 추상클래스 이다.

 

https://www.javadeploy.com/java-streams/module2/input-output-stream-subclasses.jsp

 

  • OutputStream의 주요 메소드
리턴타입 메소드 설명
void write(int b)  1byte를 출력합니다.
void write(byte[ ] b)  매개값으로 주어진 배열 b의 모든 바이트를 출력합니다.
void write(byte[ ] b, int off, int len)  매개값으로 주어진 배열 b[off]부터 len개까지의 바이트를 출력합니다.
void flush()  출력 버퍼에 잔류하는 모든 바이트를 출력합니다.
void close()  출력 스트림을 닫습니다.

 

바이트 입력 스트림 : InputStream

  • InputStream은 바이트 기반 출력 스트림의 최상위 클래스로 추상클래스 이다.
  • InputStream의 주요 메소드
리턴 타입 메소드 설명
int read()  1byte를 읽고 읽은 바이트를 리턴합니다.
int read(byte[ ] b)  읽은 바이트를 매개값으로 주어진 배열에 저장하고 읽은 바이트 수를 리턴합니다.
int read(byte[ ] b, int off, int len)  len개의 바이트를 읽고 매개값으로 주어진 배열에서 b[off]부터 len개까지 저장합니다. 그리고 읽은 바이트 수를 리턴합니다.
void close()  입력 스트림을 닫습니다.

 

문자 출력 스트림 : Writer

 

https://xzio.tistory.com/312

 

  • Writer는 문자 기반 출력 스트림의 최상위 클래스로 추상 클래스이다.
  • Writer 클래스의 주요 메소드
리턴 타입 메소드 설명
void write(int c)  매개값으로 주어진 한 문자를 보냅니다.
void write(char[ ] cbuf)  매개값으로 주어진 배열의 모든 문자를 보냅니다.
void write(char[ ] cbuf, int off, int len)  매개값으로 주어진 배열에서 cbuf[off]부터 len까지의 문자를 보냅니다.
void write(String str)  매개값으로 주어진 문자열 보냅니다.
void write(String str, int off, int len)  매개값으로 주어진 문자열에서 off 순번부터 len개까지의 문자를 보냅니다.
void flush()  버퍼에 잔류하는 모든 문자를 출력합니다.
void close()  출력 스트림을 닫습니다.

 

문자 입력 스트림 : Reader

  • Reader는 문자 기반 입력 스트림의 취상위 클래스로 추상클래스 이다.
  • Reader의 주요 메소드
리턴 타입 메소드 설명
int read()  1개의 문자를 읽고 리턴합니다.
int read(char[ ] cbuf)  읽은 문자를 매개값으로 주어진 문자 배열에 저장하고 읽은 문자수를 리턴합니다.
int read(char[ ] cbuf, int off, int len) len개의 문자를 읽고 매개값으로 주어진 문자 배열에서 cbuf[off]부터 len개까지 저장합니다. 그리고 읽은 문자 수를 리턴합니다.
void close()  입력 스트림을 닫습니다.

 


 [ 키워드 정리 ] 

  • 입출력 스트림 : 자바에서 데이터는 스트림을 통해 입출력됩니다. 프로그램이 출발지냐 또는 도착지냐에 따라서 사용하는 스트림의 종류가 결정됩니다. 프로그램이 도착지이면 흘러온 데이터를 입력받아야 하므로 입력 스트림을 사용합니다. 반대로 프로그램이 출발지면 데이터를 출력해야 하므로 출력 스트림을 사용합니다.
  • InputStream : 바이트 기반 입력 스트림의 최상위 클래스로 추상 클래스입니다. 모든 바이트 기반 입력 스트림은 InputStream 클래스를 상속받아서 만들어집니다. InputStream 클래스에는 바이트 기반 입력 스트림이 기본적으로 가져야 할 메소드가 정의되어 있습니다.
  • OutputStream : 바이트 기반 출력 스트림의 최상위 클래스로 추상 클래스입니다. 모든 바이트 기반 출력 스트림 클래스는 OutputStream 클래스를 상속받아서 만들어집니다. OutputStream 클래스에는 모든 바이트 기반 출력 스트림이 기본적으로 가져가야 할 메소드가 정의되어 있습니다.
  • Reader : 문자 기반 입력 스트림의 최상위 클래스로 추상 클래스입니다. 모든 문자 기반 입력스트림은 Reader 클래스를 상속받아서 만들어집니다. Reader 클래스에는 문자 기반 입력 스트림이 기본적으로 가져야 할 메소드가 정의되어 있습니다.
  • Writer : 문자 기반 출력 스트림의 최상위 클래스로 추상 클래스입니다. 모든 문자 기반 출력 스트림 클래스는 Writer 클래스를 상속받아서 만들어집니다. Writer 클래스는 모든 문자 기반 출력 스트림이 기본적으로 가져야 할 메소드가 정의되어 있습니다.

출처 : 혼자 공부하는 자바 - 신용권 지음

'Coding > Java' 카테고리의 다른 글

[33] JAVA 보조 스트림  (2) 2023.01.24
[31] JAVA LIFO와 FIFO 컬렉션  (0) 2022.12.25
[30] JAVA 컬렉션 프레임워크  (0) 2022.12.25
[29] JAVA 스레드 제어  (0) 2022.12.21
[28] JAVA 멀티스레드  (0) 2022.12.21
  • 후입선출(LIFO : Last In First Out) : 나중에 넣은 객체가 먼저 빠져나가는 자료구조
  • 선입선출(FIFO : First In First Out) : 먼저 넣은 객체가 먼저 빠져나가는 자료구조
  • 컬렉션 프레임워크에는 LIFO(리포) 자료구조를 제공하는 Stack 클래스와 FIFO(피포) 자료구조를 제공하는 Queue 인터페이스를 제공한다.

https://carminati.altervista.org/PROJECTS/C++/FIFO%20and%20LIFO/FIFOandLIFO.html

 

Stack

① Stack 클래스는 LIFO 자료구조를 구현한 클래스. 다음은 주요 메소드 이다.

리턴타입 메소드 설명
E push(E item)  주어진 객체를 스택에 넣습니다.
E peek()  스택의 맨 위 객체를 가져옵니다. 객체를 스택에서 제거하지 않습니다.
E pop()  스택의 맨 위 객체를 가져옵니다. 객체를 스택에서 제거합니다.

 

 

② Stack 객체를 생성하려면 저장할 객체 타입을 E타입 파라미터 자리에 표기하고 기본 생서자를 호출하면 된다.

예를 들어 String을 저장하는 Stack은 다음과 같이 생성할 수 있다.

 

③ 사용 예는 다음과 같다.

public class Coin {
    private int value;

    public Coin(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}
public class StackExample {
    public static void main(String[] args) {
        Stack<Coin> coinBox = new Stack<>();

        coinBox.push(new Coin(100));
        coinBox.push(new Coin(50));
        coinBox.push(new Coin(500));
        coinBox.push(new Coin(10));

        while (!coinBox.isEmpty()) {
            Coin coin = coinBox.pop();
            System.out.println("꺼내온 동전 = " + coin.getValue());
        }
    }
}

<실행결과>
꺼내온 동전 = 10
꺼내온 동전 = 500
꺼내온 동전 = 50
꺼내온 동전 = 100

 

Queue

① Queue 인터페이스는 FIFO 자료구조에서 사용되는 메소드를 정의한다. 다음은 Queue 인터페이스에 정의되어 있는 메소드이다.

리턴 타입  메소드  설명 
boolean  offer(E e)  주어진 객체를 넣는다. 
peek()  객체 하나를 가져온다. 객체를 큐에서 제거하지 않는다. 
pool()  개체 하나를 가져온다. 객체를 큐에서 제거한다. 

 

② Queue 인터페이스를 구현한 대표적인 클래스는 LinkedList 이다. LinkedList는 List 인터페이스를 구현했기 때문에 List 컬렉션이기도 하다. 아래는 LinkedList 객체를 Queue 인터페이스로 변환한 것

 

③ 사용 예 - 먼저 넣은 메시지가 반대쪽으로 먼저 나오기 때문에 넣은 순서대로 메시지가 처리된다.

public class Message {
    public String command;
    public String to;

    public Message(String command, String to) {
        this.command = command;
        this.to = to;
    }
}
import java.util.LinkedList;
import java.util.Queue;

public class QueueExample {
    public static void main(String[] args) {

        Queue<Message> messageQueue = new LinkedList<>();

        messageQueue.offer(new Message("sendMail","홍길동"));
        messageQueue.offer(new Message("sendSMS","신용권"));
        messageQueue.offer(new Message("sendKakaotalk","홍두께"));

        while (!messageQueue.isEmpty()) {
            Message message = messageQueue.poll();
            switch (message.command) {
                case "sendMail" :
                    System.out.println(message.to + "님에게 메일을 보냅니다.");
                    break;
                case "sendSMS" :
                    System.out.println(message.to + "님에게 SMS을 보냅니다.");
                    break;
                case "sendKakaotalk" :
                    System.out.println(message.to + "님에게 카카오톡을 보냅니다.");
                    break;
            }
        }
    }
}

<실행결과>
홍길동님에게 메일을 보냅니다.
신용권에게 SMS을 보냅니다.
홍두께님에게 카카오톡을 보냅니다.

 


참고자료 : <혼자 공부하는 자바> - 신용권

'Coding > Java' 카테고리의 다른 글

[33] JAVA 보조 스트림  (2) 2023.01.24
[32] JAVA 입출력 스트림  (0) 2022.12.28
[30] JAVA 컬렉션 프레임워크  (0) 2022.12.25
[29] JAVA 스레드 제어  (0) 2022.12.21
[28] JAVA 멀티스레드  (0) 2022.12.21
  • 컬렉션 프레임워크(Collection Framework) :자료구조를 사용해서 객체들을 효율적으로 추가, 삭제, 검색할 수 있도록 인터페이스와 구현 클래스를 java.util 패키지에서 제공하는 것
  • 컬렉션 : 객체의 저장을 의미
  • 프레임워크 : 사용 방법을 정해놓은 라이브러리를 의미
  • 컬렉션 프레임워크의 주요 인터페이스로는 List, Set, Map이 있다. 

https://www.toolsqa.com/java/data-structure/

 

List 컬렉션

  • List 컬렉션은 배열과 비슷하게 객체를 인덱스로 관리한다.
  • 배열과의 차이점은 저장 용량(capacity)이 자동으로 증가하며, 객체를 저장할 때 자동 인덱스가 부여된다는 점이다.
  • 객체 자체를 저장하는 것이 아니라 객체의 번지를 참조한다는 특징이 있다.
  • 그렇기 때문에 동일한 객체를 중복 저장할 수 있는데, 이 경우 동일한 번지가 참조된다.

 

< List 컬력션에서 공통으로 사용 가능한 List 인터페이스의 메소드 >

기능 메소드 설명
객체 추가 boolean add(E e)  주어진 객체를 맨 끝에 추가합니다.
void add(int index, E element)  주어진 인덱스에 객체를 추가합니다.
E set(int index, E element)  주어진 인덱스에 저장된 객체를 주어진 객체로 바꿉니다.
객체 검색 boolean contains(Object o)  주어진 객체가 저장되어 있는지 조사합니다.
E get(int index)  주어진 인덱스에 저장된 객체를 리턴합니다.
boolean isEmpty()  걸렉션이 비어 있는지 조사합니다.
int size()  저장되어 있는 전체 객체 수를 리턴합니다.
객체 삭제 void clear()  저장된 모든 객체를 삭제합니다.
E remove(int index)  주어진 인덱스에 저장된 객체를 삭제합니다.
boolean remove(Object o)  주어진 객체를 삭제합니다.

※ 위의 표에서 E라는 타입 파라미터는 저장되는 개체의 타입을 List 컬렉션을 생성할 때 결정하라는 뜻

 

ArrayList 

  • List<String> list = new ArrauList< >( );
  • 기본 생성자로 ArrayList 객체를 생성하면 내부에 10개의 객체를 저장할 수 있는 초기 용량을 가지게 된다.
  • ArrayList에서 특정 인덱스의 객체를 제거하면 바로 뒤 인덱스부터 마지막 인덱스까지 모두 앞으로 1씩 당겨진다. 마찬가지로 특정 인덱스에 객체를 삽입하면 해당 인덱스부터 마지막 인덱스까지 모두 1씩 밀려난다.
  • 따라서 빈번한 객체 삭제와 삽입이 일어나는 곳에서는 ArrayList를 사용하는 것 보다 LinkedList를 사용하는 것이 좋다.
  • 반면, 인덱스를 이용해서 객체를 찾거나 맨 마지막에 객체를 추가하는 경우는 ArrayList가 더 좋은 성능을 발휘한다.

Vector

  • List<E> list = new Vector<E>( );
  • ArrayList와 다른 점은 Vector는 동기화된 메소드로 구성되어 있기 때문에 멀티 스레드가 동시에 Vector의 메소드를 실행할 수 없고, 하나의 스레드가 메소드 실행을 완료해야만 다른 스레드가 메소드를 실행할 수 있다는 점이다.
  • 멀티 스레드 환경에서 안전하게 객체를 추가, 삭제할 수 있다. = 스레드 안전(thread safe)

LinkedList

  • ArrayList는 내부 배열에 객체를 저장해서 관리하지만, LinkedList는 인접 참조를 링크해서 체인처럼 관리한다.
  • List<E> list = new LinkedList<>( );
  • 특정 인덱스의 객체를 제거하면 앞뒤 링크만 변경되고 나머지 링크는 변경되지 않는다.
  • 끝에서부터(순차적으로) 추가 또는 삭제하는 경우는 ArrayList가 빠르지만, 중간에서 추가나 삭제하는 경우는 앞뒤 링크 정보만 변경되는 LinkedList가 더 빠르다.

 

Set 컬렉션

  • List 컬렉션은 객체의 저장 순서를 유지하지만, Set 컬렉션은 저장 순서가 유지되지 않는다.
  • 객체를 중복해서 저장할 수 없고, 하나의 null만 저장할 수 있다.
  • Set 컬렉션에는 HashSet, LinkedHashSet, TreeSet 등이 있다.
  • 인덱스로 관리하지 않기 때문에 인덱스를 매개값으로 갖는 메소드가 없다.

< Set 인터페이스의 메소드 >

기능 메소드 설명
객체 추가 boolean add(E e)  주어진 객체를 저장합니다. 객체가 성공적으로 저장되면 true를 리턴하고 중복 객체면 false를 리턴합니다.
객체 검색 boolean contains(Object o)  주어진 객체가 저장되어 있는지 조사합니다.
boolean isEmpty()  컬렉션이 비어있는지 조사합니다.
lterator<E> iterator()  저장된 객체를 한 번씩 가져오는 반복자를 리턴합니다.
int size()  저장되어 있는 전체 객체 수를 리턴합니다.
객체 삭제 void clear()  저장된 모든 객체를 삭제합니다.
boolean remove(Object o)  주어진 객체를 삭제합니다.

 

  • Set<String> set = ...;
  • Set 컬렉션은 인덱스로 객체를 검색해서 가져오는 메소드가 없기 때문에, 대신 전체 객체를 대상으로 한 번씩 반복해서 가져오는 반복자 Iterator를 제공한다.
  • Iterator<String> iterator = set.iterator( );

< Iterator 인터페이스에 선언된 메소드 >

리턴 타입 메소드 설명
boolean hasNext()  가져올 객체가 있으면 true를 리턴하고 없으면 false를 리턴한다.
E next()  컬렉션에서 하나의 객체를 가져온다.
void remove()  Set 컬렉션에서 객체를 제거한다.
while(iterator.hasNext()){ //저장된 객체수 만큼 루핑
	String str = iterator.next(); //String 객체 하나를 가져옴
    if(str.equals("지니")){ 
    	iterator.remove(); //객체를 제거
    }
}

 

HashSet

  • Set<E> set = new HashSet<E>();
  • 객체들을 순서 없이 저장하고 동일한 객체는 중복 저장하지 않음
  • 객체를 저장하기 전에 먼저 객체의 hashCode()메소드를 호출해서 해쉬코드를 얻어내고, 이미 저장되어 있는 객체들의 해시코드와 비교한다. 만약 동일한 해시코드가 있다면 다시 equals() 메소드로 두 객체를 비교해서 true가 나오면 동일한 객체로 판단하고 중복 저장을 하지 않는다.
  • 문자열을 저장할 경우, 같은 문자열을 갖는 String 객체는 동등한 객체로 간주된다.

 

Map 컬렉션

  • key(키) 와 value(값)로 구성된 Map.Entry 객체를 저장하는 구조로 Entry는 Map 인터페이스 내부에 선언된 중첩 인터페이스이다.
  • 키와 값은 모두 객체이다.
  • 키는 중복 저장될 수 있지만, 값은 중복 저장될 수 없다.
  • 만약 기존에 저자된 키와 동일한 키로 값을 저장하면 기존의 값은 없어지고 새로운 값으로 대체된다.
  • HashMap, Hashtable, LinkedHashMap, Properties, TreeMap 등이 있다.

 

< Map 컬렉션의 메소드 >

기능 메소드 설명
객체 추가 V put(K ket, V value)  주어진 키로 값을 저장합니다. 새로운 키일 경우 null을 리턴하고 동일한 키가 있을 경우 값을 대체하고 이전 값을 리턴합니다.
객체 검색 boolean containsKey(Object key)  주어진 키가 있는지 여부를 확인합니다.
boolean containsValue(Object value)  주어진 값이 있는지 여부를 확인합니다.
Set<Map.Entry<K,V>> entrySet()  키와 값이 쌍으로 구성된 모든 Map.Entry 객체를 Set에 담아서 리턴합니다. 
V get(Object key)  주어진 키가 있는 값을 리턴합니다.
booleab isEmpty()  컬렉션이 비어있는지 여부를 확인합니다.
Set<K> keySet()  모든 키를 Set객체에 담아서 리턴합니다.
int size()  저장된 키의 총 수를 리턴합니다.
Collection<V> value()  저장된 모든 값을 Collection에 담아서 리턴합니다.
객체 삭제 void clear()  모든 Map.Entry(키와 값)를 삭제합니다.
V remove(Object key)  주어진 키와 일치하는 Map.Entry를 삭제하고 값을 리턴합니다.

 

HashMap

  • HashMap의 키로 사용할 객체는 hashCode()와 equals()메소드를 재정의해서 동등 객체가 될 조건을 정해야 한다.
  • 객체가 달라도 동등 객체라면 같은 키로 간주하고 중복 저장되지 않도록 하기 위함이다.
  • 키와 값의 타입은 기본타입을 사용할 수 없고 클래스 및 인터페이스 타입만 사용 가능하다. 
  • 키로 String 타입을 사용하고 값으로 Integer타입을 사용하는 HashMap은 다음과 같이 생성할 수 있다.
  • Map<String, Integer> map = new HashMap<>();

Hashtable

  • HashMap과의 차이점은 Hashtable은 동기화된 메소드로 구성되어 있기 때문에 멀티 스레드가 동시에 Hashtable의 메소드를 실행할 수 없고, 하나의 스레드가 실행을 완료해야만 다른 스레드를 실행할 수 있다는 것
  • 멀티스레드 환경에서 안전하게 객체를 추가, 삭제할 수 있기 때문에 Hashtale은 스레드에 안전하다.
  • Map<String, Integer> map = new Hashtable<>();

'Coding > Java' 카테고리의 다른 글

[32] JAVA 입출력 스트림  (0) 2022.12.28
[31] JAVA LIFO와 FIFO 컬렉션  (0) 2022.12.25
[29] JAVA 스레드 제어  (0) 2022.12.21
[28] JAVA 멀티스레드  (0) 2022.12.21
[27] JAVA 기초 복습  (0) 2022.12.14

 

 

  • 스레드를 생성하고 시작하면 스레드는 다양한 상태를 가지게 된다. 스레드의 상태는 자동으로 변경될 수도 있고, 코드에 의해서 변경될 수도 있다.
  • 스레드 객체를 생성하고 start() 메소드를 호출하면 바로 실행되는 것이 아니라 실행 대기 상태가 된다.
  • 실행 대기 상태란 언제든지 실행할 준비가 되어 있는 상태를 의미한다.
  • 실행 상태의 스레드는 run() 메소드를 모두 실행하기 전에 다시 실행 대기 상태로 돌아갈 수 있고, 실행 대기 상태에 있는 다른 스레드가 선택되어 실행 상태가 되기도 한다.
  • 실행 상태에서 run() 메소드의 내용이 모두 실행되면 스레드의 실행이 멈추고 종료 상태가 된다.

 

스레드 상태

  • 실행 상태(running) : 실행 대기 상태에 있는 스레드 중에서 운영체제는 하나의 스레드를 선택하고 CPU(코어)가 run()메소드를 실행하도록 한다. 이때를 실행 상태라고 한다.
  • 종료(terminated) 상태 : 실행 상태에서 run() 메소드가 종료되면, 더 이상 실행할 코드가 없기 때문에 스레드의 실행이 멈추게 된 상태.
  • 스레드는 실행 대기 상태와 실행 상태로 번갈아 변하면서, 경우에 따라 실행 상태에서 일시 정지 상태로 가기도 한다. 일시 정지 상태는 스레드가 실행할 수 없는 상태이다. 일시 정지 상태에서는 바로 실행 상태로 돌아갈 수 없고, 일시 정지 상태에서 빠져나와 실행 대기 상태로 가야 한다.

 

스레드 상태 제어

  • 스레드 상태 제어 : 실행 중인 스레드의 상태를 변경하는 것
  • 스레드 상태 제어는 주어진 시간 동안 일시 정지시키는 sleep() 메소드와 스레드를 안전하게 종료시키는 stop 플래그, interrupt()메소드를 사용한다.
  • 아래의 그림에서 취소선으로 표시한 메소드는 스레드의 안전성을 해친다고 하여 더 이상 사용하지 않도록 권장된 Deprecated 메소드 이다.

 

메소드 설명
interrupt()  일시 정지 상태의 스레드에서 InterruptedException을 발새시켜, 예외 처리 코드(catch)에서 실행 대기 상태로 가거나 종료 상태로 갈 수 있도록 한다.
sleep(long millis) 주어진 시간 동안 스레드를 일시 정지 상태로 만든다. 주어진 시간이 지나면 자동적으로 실행 대기 상태가 된다.
stop() 스레드를 즉시 종료한다. 불안전한 종료를 유발하므로 사용하지 않는 것이 좋다.
notify(), notifyAll() 동기화 블록 내에서 wait() 메소드에 의해 일시 정지 상태에 있는 스레드를 실행 대기 상태로 만든다.
join() join() 메서드를 호출한 스레드는 일시 정지 상태가 됩니다. 실행 대기 상태로 가려면 join() 메서드를 맴버로 가지는 스레드가 종료되거나, 매개값으로 주어진 시간이 지나야 합니다.
wait() 동기화(synchronized) 블록 내에서 스레드를 일시 정지 상태로 만듭니다. 매개값으로 주어진 시간이 지나면 자동적으로 실행 대기 상태로 됩니다. 시간이 주어지지 않으면 notify(), notifyAll() 메소드에 의해 실행 대기 상태로 있습니다.

 

주어진 시간 동안 일시 정지

  • 실행 중인 스레드를 일정 시간 멈추게 하고 싶다면 Thread 클래스의 정적 메소드인 sleep()을 사용하면 된다. 다음과 같이 Thread.sleep() 메소드를 호출한 스레드는 주어진 시간 동안 일시 정지 상태가 되고, 다시 실행 대기 상태로 돌아간다.

안전한 종료

  • Thread는 스레드를 즉시 종료하기 위해서 stop()메소드를 제공하고 있는데, 이 메소드는 deprecated(중요도가 떨어져 이제 사용되지 않음)되었다.
  • 그 이유는 stop()메소드로 스레드를 갑자기 종료하면 스레드가 사용 중이던 자원들이 불안전한 상태로 남겨지기 때문이다.
  • 스레드를 안전하게 종료하기 위해서 stop플래그를 이용하거나 interrupt() 메소드를 이용하는 방법이 있다.

 

stop 플래그를 이용하는 방법

스레드는 run() 메소드가 끝나면 자동적으로 종료되므로, run() 메소드가 정상적으로 종료되도록 유도하는 것이다. 다음 코드는 stop 풀래그를 이용해서 run() 메소드의 종료를 유도한다.

public class XXXThread extends Thread{

    private boolean stop; // stop 플래그

    public void run(){
        while(!stop){
            // 스레드가 반복 실행하는 코드;
        }
        // 스레드가 사용한 자원 정리
    }
} 

위 코드에서 stop 필드가 false일 경우에는 while문의 조건식이 true가 되어 반복 실행하지만, stop 필드가 true일 경우에는 while문의 조건식이 false가 되어 while문을 빠져나온다. 그리고 스레드가 사용한 자원을 정리하고, run() 메소드가 끝나게 됨으로써 스레드는 안전하게 종료된다.

 

데몬 스레드

  • 주 스레드의 작업을 돕는 보조적인 역할을 수행하는 스레드
  • 주 스레드가 종료되면 데몬 스레드는 강제적으로 자동 종료 되는데, 주 스레드의 보조 역할을 수행하므로 주 스레드가 종료되면 데몬 스레드의 존재 의미가 사라지기 때문이다.

 


[ 참고자료 ]

 

 

멀티 스레드의 상태 제어

스레드는 객체를 생성하고, start() 메소드를 호출하면 곧바로 스레드가 실행되는 것처럼 보이지만 실은 실행 대기 상태가 됩니다. 실행 대기 상태란 아직 스케줄링이 되지 않아서 실행을 기다리

velog.io

 

'Coding > Java' 카테고리의 다른 글

[31] JAVA LIFO와 FIFO 컬렉션  (0) 2022.12.25
[30] JAVA 컬렉션 프레임워크  (0) 2022.12.25
[28] JAVA 멀티스레드  (0) 2022.12.21
[27] JAVA 기초 복습  (0) 2022.12.14
[26] JAVA 익명 객체 (Anonymous)  (0) 2022.12.10

+ Recent posts