Search

'java'에 해당되는 글 2건

  1. 2021.04.23 Thread, Runnable, Callable, ThreadPool
  2. 2018.11.25 JAVA 파일 생성/읽기/쓰기

Thread, Runnable, Callable, ThreadPool

개발/안드로이드 2021. 4. 23. 17:29 Posted by 아는 개발자

1. Thread

 

Thread 클래스는 Java 언어에서 비동기 작업시 대표적으로 사용하는 클래스다. 코틀린과 람다를 이용하면 아래와 같이 간단하게 비동기 작업 코드를 짤 수 있어서 짧은 디코딩 작업이나, 연산처리를 할 때 주로 사용된다. 

 

fun testThread() {
    val thread1 = Thread {
        Thread.sleep(1000)
        Log.d(this.toString(), "this is test thread1")
    }

    val thread2 = Thread {
        Log.d(this.toString(), "this is test thread2")
    }

    thread1.start()
    thread2.start()
}

 

그런데 Thread를 생성하는 작업은 안드로이드 밑단 운영체제에서 pthread를 생성하게 되는 작업이므로 추가적인 메모리를 할당받게 된다. 그래서 Thread를 많이 생성할수록  더 많은 메모리 공간을 차지하게되기 때문에 무한정 만들 수 없다. 

 

2. Runnable 

 

앞서 언급한 Thread를 간소화한 형태다. Thread는 클래스인 반면 Runnable은 인터페이스라서 다른 클래스를 상속하고 있는 클래스에 Runnable을 추가할 수 있고 상속 형태 없이 익명 클래스 형태로 바로 써도 된다. 실행은 run() 클래스를 호출해서 가능하다. 

 

fun testRunnable() {
    val runnable = Runnable { Log.d(this.toString(), "test runnable") }

    runnable.run()
}

 

3. Callable 

 

Runnable과 비슷하지만 Callable은 비동기 작업에서 리턴값도 줄 수 있고 결과 값을 연산하지 못하면 Exception을 발생시키기도 한다. 리턴값을 제공해야하는 비동기작업이면 Runnable 말고 Callable을 쓰면 된다. 아래 코드는 Callable에서 정수 값들을 리턴하도록 하고 각각의 합을 로그로 찍은 것이다

 

fun testCallable() {
    val callableOne = Callable { 1 }
    val callableTwo = Callable { 2 }
    val callableLog = Callable { Log.d(this.toString(), "this is callable log") }

    try {
        val merged = callableOne.call() + callableTwo.call()
        callableLog.call()

        Log.d(this.toString(), "this is callable merged: $merged")
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

 

4. ThreadPool

 

앞서 설명한 Thread, Runnable, Callable 모두 쓰레드 계열이라서 개별로 메모리를 쓰게돼, 무한정 만들면 메모리 낭비가 발생한다. 그래서 자바에서는 ThreadPool이란 것으로 쓰레드를 관리할 수 있도록 했다.  ThreadPool 관리 객체는 Executors 클래스를 통해서 생성하는데 이 클래스 검색해보면 내부의 함수를 통해 다양한 방식으로 Thread를 관리할 수 있는 것을 확인 할 수 있다. 지면상 모두 설명할 수 없고, 아래 코드에서 쓰는 newFixedThreadPool 함수만 설명하면 쓰레드를 최대 4개만 만들 수 있게 하고 나머지 작업은 재사용하겠다는 듯이다. 새로운 작업을 추가해도 쓰레드는 4개 이상 생기지 않으며 나머지는 재사용되기 때문에 메모리 낭비에 대한 부담 없이 새로운 작업을 추가할 수 있다.

 

작업은 Callable, Runnable의 형태로 추가 가능하며 submit 함수로 추가한다. 이때 리턴 값은 Future 클래스로 받게되고, get() 함수를 통해 결과 값을 얻을 수 있다.

 

fun testExecutorService() {
    val cachedPool = Executors.newFixedThreadPool(4)
    val futureOne = cachedPool.submit(Callable { 1 })
    val futureTwo = cachedPool.submit(Callable { 2 })
    val printLog = cachedPool.submit(Runnable {
        Log.d(this.toString(), "something...") })

    try {
        val merged = futureOne.get() + futureTwo.get()
        printLog.get()
        Log.d(this.toString(), "merged: $merged")

    } catch (e: Exception) {
        e.printStackTrace()
    }
}

 

728x90

JAVA 파일 생성/읽기/쓰기

기술 2018. 11. 25. 13:11 Posted by 아는 개발자

JAVA는 객체지향관점에 따라 시스템에 존재하는 파일이나 폴더를 하나의 객체로 보고 관리한다. 시스템 내에서 특정 위치의 파일을 읽거나 삭제 또는 생성하고 싶다면 해당 파일에 대한 객체를 생성해주면 된다. 파일 객체는 아래의 예제 코드처럼 파일 경로와 파일 이름을 생성자의 인자로 넣어주면 간단히 생성할 수 있다.


File file = new File(filepath + File.separator + fileName);


1. 파일 유무 확인 및 생성


파일 객체 안에는 여러가지 함수가 있는데 가장 요긴하게 쓰이는 함수는 exists() 함수다. 주로 파일을 생성하거나 사용하기 전에 해당 위치에 파일 또는 폴더가 이미 존재하는지 아닌지를 확인할 때 사용한다. 아래의 코드는 파일의 유무를 확인하고 없는 경우 파일을 생성하는 예제다. 폴더를 생성 할 때는 createNewFile을 mkdir 함수로 변경하면 된다.


if (!file.exists()) {
    try {
        file.createNewFile();
    } catch (IOException e) {
        e.printStackTrace();
    }
}


2. 파일 읽기


파일에 값을 읽을때는 FileInputStream, InputStreamReader, BufferedReader 객체를 사용한다. 예제코드를 따라가보면 세번의 객체 생성 작업이 있는 것을 볼 수 있는데 모두 방금 전에 생성한 객체를 인자로 사용한다. 이 방법은 객체가 가진 데이터 값을 변환하는과정이다.


FileInputStream은 시스템에 존재하는 파일의 byte를 획득하고 InputStreamReader는 InputStream 획득한 복수개의 byte 를 해석해 특정한 문자열 집합인 charset으로 만든다. 최종적으로 BufferedReader에서는 charset값을 읽어서 string으로 변환한다.


try {
    FileInputStream fIn = new FileInputStream(file);
    InputStreamReader isr = new InputStreamReader(fIn);
    BufferedReader inBuff = new BufferedReader(isr);

    while (true) {
        try {
            inputLine = inBuff.readLine();
        } catch(IOException e) {
            e.printStackTrace();
        }

        if (inputLine == null)
            break;

        outStringBuf.append(inputLine);
    }
} catch(FileNotFoundException e) {
    e.printStackTrace();
}


3. 파일 쓰기


파일에 값을 쓸 때는 FileOutputStream, OutputStreamWriter 객체를 사용한다. OutputStreamWriter는 Charater 형태의 stream을 byte 형태로 전환해 값을 입력 할 수 있는 객체다. OutputStreamWriter 생성시 변환한 값을 입력할 Stream 객체를 전달 받는데 이때 File 객체를 품은 FileOutputStream 객체를 사용하면 file에 값을 사용하도록 할 수 있다.


final String welcomeString = new String(initialValue);
FileOutputStream fOut = new FileOutputStream(file);
OutputStreamWriter osw = new OutputStreamWriter(fOut);

osw.write(welcomeString);
osw.flush();
osw.close();


728x90

'기술' 카테고리의 다른 글

JAVA 파일 생성/읽기/쓰기  (0) 2018.11.25
스택, 힙, 코드, 데이터영역  (6) 2018.11.10
VNC와 RDP  (2) 2018.09.12
jupyter notebook 소개  (0) 2018.08.04
URI (Uniform Resource Identifier)  (0) 2018.07.02
libgdx - Viewport  (0) 2018.06.22