-
Thread, Runnable, Callable, ThreadPool개발/안드로이드 2021. 4. 23. 17:29
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() } }
'개발 > 안드로이드' 카테고리의 다른 글
움직이는 TextView (0) 2021.05.11 5월 5일부터는 앱의 광범위한 저장공간 액세스 권한이 필요한 이유를 알려야 합니다. (0) 2021.04.30 jitpack 이란 (0) 2021.03.28 안드로이드 스튜디오를 이용한 네트워크 디버깅 (0) 2021.03.14 RoundedFrameLayout (0) 2021.03.03