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
728x90

이분 탐색이란?


순차탐색처럼 처음부터 끝까지 모든 데이터를 확인하여 찾는 것이 아니라
정렬되어 있는 데이터를 대상으로 탐색범위를 절반씩 줄여가며 찾아가는 탐색 방법.

이분 탐색의 전제 조건은 정렬되어 있는 데이터를 대상으로 한다는 것.

 

 

탐색 과정


1 2 3 4 5 6 이라는 값에서 4를 찾는다면
배열의 중간에 위치한 3을 골라 4와 비교하여
찾아야하는 값인 4가 3보다 크므로
3보다 왼쪽에 위치한 값은 탐색하지 않고
3보다 큰 값들인 오른쪽에 위치한 값들의 대상으로 다시 탐색 시도

 

3보다 큰 값인 4부터 6중 다시 중간값 5와 비교하여 4는
5보다 작으므로 5의 왼쪽 값들을 대상으로 탐색 시도
5의 왼쪽값은 4밖에 없으므로 4와 4를 비교하여 일치하므로 탐색 종료

 

만약 해당 자리에 4가 아닌 다른 값이 있었다면 탐색종료
그 외 값을 찾지 못할 때 탐색 종료는 인덱스를 판단해서 결정

 

 

예제 그림


이분 탐색 과정 (이미지를 클릭해야 전 과정이 보여짐)

 

 

효율성


처음부터 끝까지 원하는 값을 찾을 때까지 탐색을 계속하는 순차 탐색은

Worst Case일 때 O(n)의  시간 복잡도를 보여줌.
10만개의 데이터가 있다면 10만번 탐색 시도.

그러나, 이분 탐색은 탐색 대상을 절반씩 계속해서 줄여나가기 때문에

Worst Case일 때 O(log N) 이 됨.
10만개의 데이터가 있다고 하더라도 약 16번 정도로 탐색을 끝낼 수 있음. 

Best Case는 중간값이 탐색 대상일때니까 O(1).

 

 

 

관련 문제

https://www.acmicpc.net/problem/1920
https://www.acmicpc.net/problem/1654
https://www.acmicpc.net/problem/1300
https://www.acmicpc.net/problem/10816

 

 

참고 사이트

https://satisfactoryplace.tistory.com/39
https://wootool.tistory.com/62

 

[알고리즘] 이분 탐색(Binaray Search)

이분 탐색(Binary Search) 정렬되어 있는(이분 탐색의 주요 조건) 배열에서 데이터를 찾으려 시도할 때, 순차탐색처럼 처음부터 끝까지 하나씩 모든 데이터를 체크하여 값을 찾는 것이 아니라 탐색 범위를 절반씩..

satisfactoryplace.tistory.com

 

추천 사이트

https://anster.tistory.com/152
https://blockdmask.tistory.com/167

 

C++ 이진 탐색(Binary Search) 구현 및 흔히 발생하는 오류

이진 탐색 전 아직 Donald Knuth 의 The art of computer programming 을 본적은 없습니다만, 스택오버플로우에 올라온 질문 에 의하면, 이런 말을 했다고 합니다. “Although the basic idea of binary search is..

anster.tistory.com

 

728x90

+ Recent posts