728x90

스레드 정보

Thread 클래스에서 제공하는 메서드를 이용하여 스레드의 정보를 확인할 수 있음

public class ThreadInfoMain {

    public static void main(String[] args) {
        // main 스레드
        Thread mainThread = Thread.currentThread();
        log("mainThread = " + mainThread);
        log("mainThread.threadId()=" + mainThread.threadId());
        log("mainThread.getName()=" + mainThread.getName());
        log("mainThread.getPriority()=" + mainThread.getPriority());
        log("mainThread.getThreadGroup()=" + mainThread.getThreadGroup());
        log("mainThread.getState()=" + mainThread.getState());

        // myThread 스레드
        Thread myThread = new Thread(new HelloRunnable(), "myThread");
        log("myThread = " + myThread);
        log("myThread.threadId()=" + myThread.threadId());
        log("myThread.getName()=" + myThread.getName());
        log("myThread.getPriority()=" + myThread.getPriority());
        log("myThread.getThreadGroup()=" + myThread.getThreadGroup());
        log("myThread.getState()=" + myThread.getState());
    }
}

 

스레드 생명주기

스레드 생명주기

 

스레드 상태

 

상태 설명 상태 전이
NEW 스레드가 생성되었으나 아직 시작되지 않은 상태 • NEW → RUNNABLE: start() 호출
RUNNABLE 스레드가 실행 중이거나 실행될 준비가 된 상태 • RUNNABLE → BLOCKED: 스레드가 lock을 얻지 못한 경우

• RUNNABLE → WAITING: wait() , join() 호출

• RUNNABLE → TIMED_WAITING: sleep(long millis) , wait(long timeout) , join(long millis) 호출

• RUNNABLE → TERMINATED: 스레드 실행 완료
BLOCKED 스레드가 동기화 락을 기다리는 상태 • BLOCKED → RUNNABLE: lock 얻은 경우
WAITING 스레드가 무기한으로 다른 스레드의 작업을 기다리는 상태 • WAITING → RUNNABLE: notify() 또는 notifyAll() 호출, join() 이 완료될 때
TIMED_WATING 스레드가 일정 시간 동안 다른 스레드의 작업을 기다리는 상태 • TIMED_WATING → RUNNABLE: 설정한 시간 경과 후
TERMINATED 스레드의 실행이 완료된 상태  

 

 

join()

특정 스레드가 완료될 때 까지 기다려야 하는 상황에서 사용

  • 특정 스레드의 작업이 완료될 때까지 기다리는 작업을 sleep()을 통해서 구현하면 정확한 종료 시점을 예측할 수 없음
  • join()을 사용하면 특정 스레드가 종료될 때까지 기다릴 수 있음

다만 단순히 join()을 사용하면 다른 스레드가 완료될 때까지 무기한 기다림

  • 이러한 경우 join(long millis)를 사용하여 타임아웃을 지정할 수 있음

 

interrupt(), isInterrupted(), interrupted()

특정 스레드의 작업을 중간에 중단하는 방법

  • 가장 쉬운 방법은 변수로 flag를 설정하여 스레드가 종료되도록 하는 방법
  • 스레드 내부에서 flag를 확인하기 때문에 스레드 내 로직(e.g. sleep()) 또는 flag 검사 주기에 따라 바로 종료되지 않을 수 있음

WAITING, TIMED_WAITING 상태의 스레드를 직접 깨워서 RUNNABLE 상태로 전환시키는 방법

  • 예를 들어 sleep()에 의해 TIMED_WAITING 상태에 있는 스레드를 깨우기 위해 interrupt()를 호출하면 아래 동작 실행
    • InterruptedException 발생
      • interrupt() 를 호출했다고 해서 즉각 InterruptedException 이 발생하는 것은 아님
      • sleep()처럼 InterruptedException을 던지는 메서드가 호출 또는 실행될 때 예외가 발생
    • TIMED_WAITING 상태에서 RUNNABLE 상태로 전이
    • catch 블록 내 코드가 실행 (RUNNABLE 상태여야 catch 블록 내 코드가 실행될 수 있음)
  • interrupt 상태는 interrupt()를 호출 시 true로 변경되고, InterruptedException이 발생하면 false로 변경됨

InterruptedException에 대한 catch 구문으로만 스레드를 중단하는 경우 InterruptedException을 던지지 않는 부분(e.g. log 출력)은 그대로 실행되고 다음 코드로 진행

  • 더욱 빠르게 작업을 중단하고 싶다면 Thread.interrupted()를 통해 인터럽트 상태를 확인하여 스레드를 종료할 수 있음
    • 인터럽트 상태인 경우 true를 반환하고, 인터럽트 상태를 false로 변경
    • 인터럽트 상태가 아닌 경우 false를 반환, 인터럽트 상태 변경 없음
  • 만약 isInterrupted() 값을 통해 스레드의 인터럽트 상태를 확인하여 스레드를 종료하는 경우 InterruptedException이 발생하지 않기 때문에 인터럽트 상태가 변경되지 않음 (isInterrupted() = true)
    • 이 경우 인터럽트 상태이기 때문에 이후 코드에서 sleep()처럼 InterruptedException을 던지는 메서드가 실행되면 해당 위치에서 기대하지 않았던 InterruptedException이 발생할 수 있음
public class Main {

  public static void main(String[] args) {
    MyTask task = new MyTask();
    Thread thread = new Thread(task, "work");
    thread.start();

    sleep(100); // 시간을 줄임
    log("작업 중단 지시 thread.interrupt()");
    thread.interrupt();
    log("work 스레드 인터럽트 상태1 = " + thread.isInterrupted());
  }

  static class MyTask implements Runnable {

    @Override
    public void run() {
      // while (!Thread.currentThread().isInterrupted()) { // 인터럽트 상태 변경X
      while (!Thread.interrupted()) { // 인터럽트 상태 변경O
        log("작업 중");
      }
      log("work 스레드 인터럽트 상태2 = " + Thread.currentThread().isInterrupted());

      try {
        log("자원 정리");
        Thread.sleep(1000);
        log("자원 종료");
      } catch (InterruptedException e) {
        log("자원 정리 실패 - 자원 정리 중 인터럽트 발생");
        log("work 스레드 인터럽트 상태3 = " + Thread.currentThread().isInterrupted());
      }
      log("작업 종료");
    }
  }
}

 

yield

스레드의 상태를 유지(RUNNABLE 상태)하면서 다른 스레드에게 CPU를 양보(OS에 힌트를 제공)하는 메서드

  • sleep()을 사용하는 경우 RUNNABLETIMED_WAITINGRUNNABLE로 상태가 전이되는 과정을 거치고, 특정 시간동안 스레드가 실행되지 않음
  • 반면 yield()를 사용하는 경우 RUNNABLE 상태로 유지(스케줄링 큐 대기)되고, 다른 스레드에게 CPU를 양보하고 다시 스케줄링 큐에 들어가서 CPU를 할당받음

만약 무의미한 작업이 반복돼서 CPU를 점유하는 경우 yield()를 호출을 통해 다른 스레드에게 CPU를 양보하여 성능을 향상시킬 수 있음

728x90

'Java > 멀티스레드' 카테고리의 다른 글

[JAVA] 스레드 생성과 실행  (1) 2024.09.18
728x90

스레드 생성

  • Thread 클래스를 상속받아 run() 메서드를 오버라이딩하여 스레드를 생성
  • Runnable 인터페이스를 구현하여 스레드를 생성

 

Thread 클래스 상속

스레드 클래스 정의

public class HelloThread extends Thread {

    @Override
    public void run() {
        doSomething();
    }
}

 

스레드 생성 및 실행

  • start() 메서드를 호출하여 스레드를 실행
    • main 스레드와 별도의 스레드를 실행
  • run() 메서드를 직접 호출하면 main 스레드에서 실행
    • main 스레드는 HelloThread 인스턴스에 있는 run() 메서드를 호출하는 형태
public class HelloThreadMain {

    public static void main(String[] args) {
        HelloThread helloThread = new HelloThread();
        helloThread.start();
    }
}

 

 

데몬 스레드

스레드는 사용자(user) 스레드와 데몬(daemon) 스레드로 구분

차이는 JVM 종료 시점

  • 모든 user 스레드가 종료되면 JVM도 종료
  • 데몬 스레드는 user 스레드가 모두 종료되면 데몬 스레드도 종료 (why? JVM이 종료돼서)

setDaemon(true) 메서드를 호출하여 데몬 스레드로 설정

  • 데몬 스레드 여부는 start() 실행 전에 결정 (이후에 수정 불가)
public class DaemonThreadMain {

    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getName() + ": main() start");
        DaemonThread daemonThread = new DaemonThread();
        daemonThread.setDaemon(true); // 데몬 스레드 여부
        daemonThread.start();
        System.out.println(Thread.currentThread().getName() + ": main() end");
    }

  static class DaemonThread extends Thread {

    @Override
    public void run() {
      System.out.println(Thread.currentThread().getName() + ": run()");
      try {
        Thread.sleep(10000); // 10초간 실행
      } catch (InterruptedException e) {
        throw new RuntimeException(e);
      }

      System.out.println(Thread.currentThread().getName() + ": run() end");
    }
  }
}

 

 

run() 메서드 안에서 Thread.sleep() 를 호출할 때 checked exception 인 InterruptedException 을 밖으로 던질 수 없고 반드시 잡아야 함

  • why? run() 메서드는 부모 클래스 Thread의 인터페이스인 Runnable 인터페이스에서 throws를 선언하지 않고 있음
    • 자바 오버라이드 규칙에 따라 부모 메서드 또는 인터페이스가 체크 예외를 던지지 않는 경우, 재정의된 자식 메서드도 체크 예외를 던질 수 없음
  • InterruptedException은 checked exception 이기 때문에 try-catch 블록으로 예외를 잡아야 함

 

 

Runnable 인터페이스 구현

Runnable 인터페이스를 구현하는 방식으로 스레드를 생성

public interface Runnable {
     void run();
}
 public class HelloRunnable implements Runnable {
     @Override
     public void run() {
         System.out.println(Thread.currentThread().getName() + ": run()");
     }
}

 

Thread 상속 vs Runnable 구현

스레드 사용할 때는 Thread 를 상속 받는 방법보다 Runnable 인터페이스를 구현하는 방식을 사용하자

 

  • 자바는 다중 상속이 안 된다 -> Thread 클래스를 상속받으면 다른 클래스를 상속받을 수 없음
  • 코드의 분리가 안 된다 -> 굳이 Thread 클래스를 상속받아서 디펜던시 및 추가적인 메모리를 할당 할 필요가 없음
  • 여러 스레드가 동일한 Runnable 객체를 공유할 수 있어 자원 관리를 효율적으로 할 수 있다 -> Runnable 인스턴스를 여러 스레드에서 사용할 수 있음 (개별 스레드에서 run() 참조 값이 같음)
728x90

'Java > 멀티스레드' 카테고리의 다른 글

[JAVA] 스레드 제어와 생명주기  (0) 2024.09.18
728x90

TCP/IP 프로토콜

  • TCP : Transmission Control Protocol
    - 두 시스템 간에 신뢰성 있는 데이터의 전송을 관장하는 프로토콜
  • IP : Internet Protocol
    - 패킷 교환 네트워크에서 호스트간 데이터를 주고 받는 것을 관장하는 프로토콜

cf. OSI 7계층 관련 글
cf. TCP vs UDP 관련 글
cf. IP주소, 포트 번호, URL 관련 글

자바의 URL 클래스

  • java.net 패키지에 포함

URL 객체 생성 방법

  1. 절대 경로로 URL 객체 생성
URL myGithub = new URL("https://github.com/ruthetum");
  1. 상대 경로로 URL 객체 생성
URL repo = new URL(myGithub, "speech-to-text-icampus");
// repo 객체가 담은 URL은 https://github.com/ruthetum/speech-to-text-icampus
  • 잘못된 주소의 URL을 입력할 경우 MalformedURLException 예외 발생

예제 : URL 주소에서 데이터(html) 읽기

public static void main(String[] args) {
        URL myGithub = null;
        try {
            myGithub = new URL("https://github.com/ruthetum");
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(myGithub.openStream()));

            String html;
            while ((html = bufferedReader.readLine()) != null) {  // 한 줄씩 읽기
                System.out.println(html);
            }
            bufferedReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

URLConnection 클래스

  • 주어진 원격지의 주소 URL에 네트워크 접속 후 데이터를 보내거나 받을 수 있도록 하는 기능
  • 단순히 url에 접속하는 것도 가능하지만 파라미터를 설정해서 값을 넣어줄 수도 있음
  • 자바로 크롤링을 할 경우 Jsoup 패키지를 참고하자
URL url = new URL("https://github.com/ruthetum");
URLConnection conn = url.openConnection();

서버에 데이터를 보내기 위한 단계

  • 자바 프로그램이 웹 서버에 데이터를 보내기 위해 필요한 단계
  1. URL 생성
  2. URL 객체에서 URLConnection 객체를 얻어옴
  3. setDoOutput() 메소드로 doOutput 필드를 true로 설정
  4. connect() 메소드로 연결 설정
  5. 연결에서 출력 스트림을 얻음
  6. 출력 스트림에서 데이터를 출력
  7. 출력 스트림을 close() 메소드로 닫음

소켓 프로그래밍

Socket(소켓)

  • 네트워크 상에서 수행되는 두 프로그램 간의 양방향 통신 링크의 끝 단을 의미
  • 소켓은 특정 포트 번호와 연결되어 있음
  • 자바에서 데이터 통신 시 소켓 사용
  • 서버 소켓, 클라이언트 소켓으로 구성

ServerSocket 클래스

  • 서버 소켓에 사용되는 클래스
  • java.net 패키지에 포함
  • 주요 생성자
  • 주요 메소드
  • 예제 코드
// 서버 소켓 생성
ServerSocket server = new ServerSocket(5000);
// 클라이언트 접속 대기
Socket socket = server.accept();
// 네트워크 입출력 스트림 생성
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedWriter out = new BufferedWriter((new OutputStreamWriter(socket.getOutputStream()));
// 클라이언트로부터 데이터 수신
String line = in.readline(); // 한 행 수신
// 클라이언트에게 데이터 전송
out.write("Hello, Client\n");
out.flush();
// 네트워크 접속 종료
socket.close();
// 서버 종료
server.close();
  • flush를 호출하면 스트림 속에 데이터를 남기지 않고 모두 전송

Socket 클래스

  • 클라이언트 소켓에 사용되는 클래스
  • java.net 패키지에 포함
  • 주요 생성자
  • 주요 메소드
  • 예제 코드
// 클라이언트 소켓 생성
Socket client = new Socket("128.12.1.1", 5000);
// 네트워크 입출력 스트림 생성
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
BufferedWriter out = new BufferedWriter((new OutputStreamWriter(client.getOutputStream()));
// 서버로 데이터 전송
out.write("hello\n");
out.flush;
// 접속 종료
client.close();

예제 : 채팅 프로그램 만들기

이미지 출처 : 명품 JAVA 프로그래밍 (황기태, 김효수 저)

728x90

'Java > Java 기본' 카테고리의 다른 글

[JAVA] 입출력 스트림과 파일 입출력  (0) 2022.12.26
[JAVA] 제네릭과 컬렉션  (0) 2022.12.26
[JAVA] 상속  (0) 2022.12.26
728x90

스레드(Thread)

  • 프로그램 코드를 이동하면서 실행하는 하나의 제어

자바의 멀티태스킹

  • 멀티쓰레딩만 가능
    - 자바에 프로세스 개념은 존재하지 않고, 스레드 개념만 존재
    • 스레드는 실행 단위이자 스케쥴링 단위
  • 하나의 응용 프로그램은 여러 개의 스레드로 구성 가능

자바 스레드

  • JVM(Java Virtual Machine)에 의해 스케쥴되는 실행 단위의 코드 블럭
  • 스레드의 생명 주기는 JVM에 의해 관리
  • 하나의 JVM은 하나의 자바 응용 프로그램만 실행
    - 하나의 응용 프로그램은 하나 이상의 스레드로 구성 가능

스레드를 만드는 2가지 방법

  • java.lang.Thread 클래스를 이용하는 경우
  • java.lang.Runnable 인터페이스를 이용하는 경우

1. Thread 클래스를 이용한 스레드 생성

1) Thread 클래스 상속, 새 클래스 작성
2) run() 메소드 오버라이딩

class TestThread extends Thread {
    ...
    public void run() {
    	// run() 메소드 오버라이딩
        ...
    }
}

3) 스레드 객체 생성

TestThread thread = new TestThread();

4) 스레드 시작 - start() 메소드 호출

thread.start();
  • 주의 사항
    - run() 메소드가 종료되면 스레드는 종료됨
    - 한 번 종료된 스레드는 다시 시작할 수 없음 = 다시 스레드 객체를 생성하고 등록해야 함
    - 스레드에서 다른 스레드를 강제 종료 가능

2. Runnable 인터페이스로 스레드 생성

1) Runnable 인터페이스로 새 클래스 구현
2) 스레드 코드 작성

class TestRunnable implements Runnable {
	...
    public void run() {
    	// run() 메소드 구현
        ...
    }
}

3) 스레드 객체 생성

Thread thread = new Thread(new TestRunnable());

4) 스레드 시작

thread.start();

Thread 클래스 상속과 Runnable 인터페이스 구현의 차이

  • 자바는 다중 상속을 지원하지 않는다. 그렇기 때문에 Thread 클래스를 상속받는 경우, 다른 클래스를 상속받을 수 없다. 그렇기 때문에 Runnable 인터페이스를 구현하는 것이 일반적이다.

스레드 상태 6가지

  • NEW : 스레드가 생성되었지만 아직 실행할 준비가 되지 않음
  • RUNNABLE : 스레드가 JVM에 의해 실행되고 있거나 실행 준비되어 스케쥴링을 기다리는 상태
  • WAITING : 다른 스레드가 notify(), notifyAll()을 불러주기를 기다리고 있는 상태, 보통 스레드 동기화를 위해 사용
  • TIMED_WAITING : 스레드가 sleep(n)을 호출하여 n ms동안 잠을 자는 상태
  • BLOCK : 스레드가 I/O 작업 요청을 하면 JVM이 자동으로 BLOCK 상태로 만듦
  • TERMINATED : 스레드 종료

스레드 생명 주기

스레드 종료와 다른 스레드 강제 종료

  • 스스로 종료하는 경우 : run() 메소드 리턴
  • 다른 스레드에서 강제 종료하는 경우 : interrupt() 메소드 사용
class TestThread extends Thread {
	int n=0;
    public void run() {
    	while(true) {
            n++;
            try {	
                Thread.sleep(1000);
            } catch (InterruptedException e) {
            	return;	// 예외 처리로 종료
            }
        }
    }
}
public class InterruptEx {
    public static void main(Stirng[] args) {
        TestThread thread = new TestThread();
        thread.start();
        thread.interrupt(); // 스레드 강제 종료
    }
}

flag를 이용한 종료

  • 스레드 안의 flag 변수를 이용하여 종료
class TestThread extends Thread {
	int n=0;
    bool flag = false; // false로 초기화
    public void finish() {
    	flag = true;
    }
    public void run() {
    	while(true) {
            n++;
            try {
                Thread.sleep(1000);
                if (flag == true)
                	return;
            } catch (InterruptException e) {
            	return;
            }
        }
    }
}
public FlagEx {
	public static void main(String[] args) {
    	TestThread thread = new TestThread();
        thread.start();        
        tread.finish();	// TestThread 강제 종료
    }
}

스레드 동기화 (Thread Synchronization)

  • 멀티스레드 프로그램 작성 시 주의점
    - 다수의 스레드가 공유 데이터에 동시에 접근하는 경우
    - 공유 데이터의 값에 예상치 못한 결과 발생 가능
  • 이를 해결하기 위해 스레드 동기화 사용
  • 공유 데이터를 접근하는 모든 스레드를 관리
  • 한 스레드가 공유 데이터에 접근하는 경우 작업이 끝날 때까지 다른 스레드들은 대기

synchronized

  • 한 스레드가 독점적으로 실행해야 하는 부분을 표시하는 키워드
  • synchronized 메소드
synchronized void add() {
	int n = getCurrentSum();
    n+=10;
    setCurrentSum(n);
}
  • synchronized 코드 블럭
void execute() {
	...
    synchronized(this) {
    	int n = getCurrentSum();
        n+=10;
        setCurrentSum(n);
    }
    ...
}

wait(), notify(), notifyAll()

  • 동기화 객체 : 2개 이상의 스레드 사이에 동기화 작업에 사용되는 객체
  • 동기화 메소드
    • synchronized 블록 내에서만 사용되어야 함
    • wait()
      • 다른 스레드가 notify()를 불러줄 때까지 대기
    • notify()
      • wait()을 호출하여 대기 중인 스레드를 깨우고 RUNNABLE 상태로 만듦
      • 2개 이상의 스레드가 대기 중이어도 한 개의 스레드만 깨움
    • notifyAll()
      • wait()를 호출하여 대기 중인 모든 스레드를 깨우고 모두 RUNNABLE 상태로 만듦

이미지 출처 : 명품 JAVA 프로그래밍 (황기태, 김효수 저)

728x90
728x90

자바의 스트림(Stream)

  • 자바 스트림은 입출력 장치와 자바 응용 프로그램 연결
  • 입력 스트림 : 입력 장치 -> 자바 프로그램
  • 출력 스트림 : 자바 프로그램 -> 입력 장치
  • 입출력 스트림 기본 단위 : 바이트
  • 바이트 입출력 스트림 : 단순 바이트 스트림 처리 (Ex. binary 파일)
  • 문자 입출력 스트림 : 문자만 입출력하는 스트림 (Ex. txt 파일)

바이트 스트림

1. FileInputStream

  • 파일 읽기
FileInputStream fin = new FileInputStream("c:\\test.txt");
int c;
while((c = fin.read()) != -1) {  // 파일의 끝을 만나면 -1 return
    System.out.print((char)c); 
}

2. FileOutputStream

  • 파일 쓰기
FileOutputStream fos = new FileOutputStream("c:\\test.out");
int num[]={1,4,-1,88,50};
byte b[]={7,51,3,4,1,24};
for(int i=0; i<num.length; i++) {
    fos.write(num[i]);
}
fos.write(b); 
fos.close();

문자 스트림

  • 유니코드로 된 문자를 입출력하는 스트림
  • Reader / Writer
  • InputStreamReader / OutputStreamWriter : 바이트 스트림과 문자 스트림을 연결
  • FileReader / FileWriter : 텍스트 파일에서 문자 데이터 입출력

1. FileReader

  • 텍스트 파일 읽어 오기
FileReader fileReader;
try {
    fileReader = new FileReader("c:\\windows\\system.ini");
    int c;
    while ((c = fileReader.read()) != -1) {  // 한 문자씩 읽음
        System.out.print((char) c);
    }
    fileReader.close();
} catch (IOException e) {
    e.printStackTrace();
}

2. InputStreamReader

  • 한글 텍스트 파일 읽어 오기
InputStreamReader inputStreamReader;
FileInputStream fileInputStream;

try {
    fileInputStream = new FileInputStream("c:\\Users\\Dell\\Desktop\\test.txt");
    inputStreamReader = new InputStreamReader(fileInputStream);

    int c;
    while ((c = inputStreamReader.read()) != -1) {
        System.out.print((char) c);
    }

    inputStreamReader.close();
    fileInputStream.close();
} catch (IOException e) {
    e.printStackTrace();
}

3. FileWriter

  • 텍스트 파일에 키보드로 입력한 값 저장하기
Scanner sc = new Scanner(System.in);
FileWriter fileWriter;
int c;

try {
    fileWriter = new FileWriter("c:\\Users\\Dell\\Desktop\\test.txt");
    String line = sc.nextLine();
    fileWriter.write(line);
    sc.close();
    fileWriter.close();
} catch (IOException e) {
    e.printStackTrace();
}
728x90

'Java > Java 기본' 카테고리의 다른 글

[JAVA] 네트워크  (0) 2022.12.26
[JAVA] 제네릭과 컬렉션  (0) 2022.12.26
[JAVA] 상속  (0) 2022.12.26
728x90

컬렉션

  • 요소(element)라고 불리는 가변 개수의 객체들의 저장소
  • 객체들의 컨테이너라고도 불림
  • 고정 크기의 배열을 다루는 어려움 해소
  • 다양한 객체를 삽입, 삭제 검색 할 수 있음
  • 컬렉션은 제네릭 기법으로 구현됨

제네릭

  • 특정 타입만 다루지 않고 여러 종류의 타입으로 변신할 수 있도록 클래스나 메서드를 일반화시키는 기법
Vector<E>	// 제네릭 벡터
Vector<Integer>	// 정수만 다루는 벡터
Vector<Stirng> // 문자열만 다루는 벡터

ArrayList<E>

  • 가변 크기의 배열
ArrayList<Integer> = new ArrayList<>();

ArrayList 주요 메서드

Iterator<E>

  • 컬렉션의 순차 검색에 이용

Iterator 주요 메서드

  • iterator() 메서드
    • 메서드를 호출하면 Iterator 객체 반환
    • Iterator 객체를 이용하여 index 없이 순차 검색 가능
Iterator<Integer> it = al.iterator();
while(it.hasNext()) {
	int n = it.next();
  	System.out.println(n);
}
Iterator 개념을 접했다면 for, while과 같은 반복문과 비교했을 때 속도 비교에 관하여 궁금증이 생길 수 있다.
해당 내용과 관련해서 잘 정리된 포스트가 있어 링크를 남긴다.
반복문 속도 비교 링크: https://3colored.tistory.com/5

HashMap<E>

  • 키(key)와 값(value)의 쌍으로 구성되는 요소를 다루는 컬렉션
  • 주요 메서드
    - put() : 요소 삽입
    - get() : 요소 검색 (값 접근의 경우 키를 이용)

LinkedList<E>

  • ArrayList 클래스와 유사하게 작동
  • element 객체들은 양방향으로 연결되어 관리
  • element 객체는 맨 앞, 맨 뒤 또는 인덱스를 이용하여 중간에 삽입 가능
  • 스택이나 큐로 사용 가능

Collections 클래스

  • 컬렉션에 대해 연산 수행, 결과로 컬렉션 return
  • 모든 메서드는 static 타입
  • 주요 메서드
    - sort() : 정렬
    - reverse() : element의 순서를 반대로
    - max(), min() : 최댓값, 최솟값
    - binarySearch() : 특정 값 검색

제네릭 객체 생성 - 구체화

  • 타입 매개 변수에 기본 타입은 사용할 수 없음 (Ex. int)

이미지 출처 : 명품 JAVA 프로그래밍 (황기태, 김효수 저)

728x90

'Java > Java 기본' 카테고리의 다른 글

[JAVA] 네트워크  (0) 2022.12.26
[JAVA] 입출력 스트림과 파일 입출력  (0) 2022.12.26
[JAVA] 상속  (0) 2022.12.26
728x90

상속(Inheritance)

  • 상위 클래스의 특성을 하위 클래스에 물려주는 것 (Ex. 자동차 -> 스포츠카 )
  • superclass : 특성을 물려주는 상위 클래스
  • subclass : 특성을 물려받는 하위클래스
public class Car {
    ...
}

public class SportsCar extends Car {
    ...
}

public class Lamborghini extends SportsCar {
    ...
}

자바 상속

  • 클래스를 다중 상속 지원하지 않음 (cf. Python)
  • 상속 횟수는 무제한
  • 최상위 클래스는 java.lang.Object

슈퍼 클래스와 서브 클래스

  • 서브 클래스의 객체에는 슈퍼 클래스가 멤버가 포함
    • 슈퍼 클래스의 private 멤버는 상속되지만 서브 클래스에서 직접 접근 불가
    • 슈퍼 클래스 내의 public 또는 protected 메서드를 통해 접근 가능

캐스팅

  • 업캐스팅(upcasting) : 서브 클래스의 레퍼런스 값을 슈퍼 클래스 레퍼런스에 대입
    • 슈퍼 클래스의 멤버만 접근 가능
  • 다운캐스팅(downcasting) : 슈퍼 클래스 레퍼런스를 서브 클래스 레퍼런스에 대입
    • 업캐스팅된 것을 다시 원래대로 되돌림
  • instanceof
    • 업캐스팅된 레퍼런스는 객체의 진짜 타입을 구분하기 어려움
    • instanceof 연산자를 통해 객체의 진짜 타입 식별
    • true/false로 값 return
class Person {
    ...
}

class Student extends Person{
    ...
}

public static void main(String[] args) {
    Person p = new Student();   // upcasting
    Student s;
    s = (Student) p;    // downcasting
    if (p instanceof Person)    // true
    if (p instanceof Student)   // false
    if (s instanceof Person)    // false
    if (s instanceof Student)   // true
}

메서드 오버라이딩 (Method Overriding)

  •  슈퍼 클래스의 메소드를 서브 클래스에서 재정의
  • 메소드 이름, 인자, 타입, 개수, 리턴 타입 등을 모두 동일하게 작성
  • static, private, final 메서드는 오버라이딩 불가
class Person {
    String name;
    ...
    void info() {
        System.out.println("사람 : " + this.name);
    }
}

class Student extends Person{
    void info() {
        System.out.println("학생 : " + this.name); // Overriding
    }
}

 

오버라이딩과 오버로딩을 혼동하지 말자

Overriding vs Overloading

추상 메소드 (abstract method)

  • 선언되어 있으나 구현되어 있지 않은 메서드
  • abstract 키워드로 선언 (Ex. public abstract int getValue();)
  • 서브 클래스에서 오버라이딩해서 구현

추상 클래스 (abstract class)

  • 추상 메서드를 하나라도 가진 가진 클래스 or 클래스 앞에 abstract로 선언한 클래스
  • 추상 클래스는 인스턴스를 생성할 수 없다.
abstract class Person {
    public String name;
    abstract public void walk();
}

추상 클래스의 용도

  • 설계와 구현 분리
  • 서브 클래스마다 목적에 맞게 추상 메소드를 다르게 구현

인터페이스 (inferface)

  • 모든 메서드가 추상 메서드인 클래스
  • 인터페이스는 상수와 추상 메서드로만 구성, 변수 필드 선언 불가
  • 객체 생성 불가, 레퍼런스 변수는 선언 가능
  • interface 키워드로 선언 (Ex. public interface Driver{})
public interface Car {
    int MAX_SPEED = 300;    // static fianl 생략, 상수 필드 선언
    int drive(int speed);   // abstract public 생략, 추상 메소드 선언
}

new Car();  // Error : inferface는 객체 생성 불가
Car car;    // 레퍼펀스 변수는 선언 가능

인터페이스 다중 구현

  • 인터페이스를 이용하여 다중 상속 구현 가능
inferface USBModule {
    void connectUSB();
}

inferface PrintModule{
    void setColor();
    void printAll();
}

public class PrintDriver implements USBModule, PrintModule {
    void connectUSB() {...};
    void setColor() {...};
    void printAll() {...};
    
    // 추가적으로 다른 메소드 작성 가능
    boolean getState() {...}
}

 

 

이미지 출처 : 명품 JAVA 프로그래밍 (황기태, 김효수 )

728x90

'Java > Java 기본' 카테고리의 다른 글

[JAVA] 네트워크  (0) 2022.12.26
[JAVA] 입출력 스트림과 파일 입출력  (0) 2022.12.26
[JAVA] 제네릭과 컬렉션  (0) 2022.12.26

+ Recent posts