Pair
를 활용해서 두 개의 인스턴스 리턴 var chicken = Chicken()
var eggs = chicken.getEggs()
var listEggs = eggs.toList()
// first, second로 관리
// var firstEgg = eggs.first
// var secondEgg = eggs.second
// 리스트로 관리
var firstEgg = listEggs[0]
var secondEgg = listEggs[1]
println("달걀의 종류는 ${eggs} 입니다.")
println("리스트 달걀의 종류는 ${listEggs} 입니다.")
println("첫번째 달걀의 종류는 ${firstEgg} 입니다.")
println("두번째 달걀의 종류는 ${secondEgg} 입니다.")
}
class Chicken {
fun getEggs(): Pair<String, String> {
var eggs = Pair("달걀", "맥반석")
return eggs
}
}
Triple
를 활용해서 세 개의 인스턴스 리턴fun main() {
var chicken = Chicken()
var eggs = chicken.getThreeEggs()
var listEggs = eggs.toList()
// first, second, third로 관리
// var firstEgg = eggs.first
// var secondEgg = eggs.second
// var eggTime = eggs.third
// 리스트로 관리
var firstEgg = listEggs[0]
var secondEgg = listEggs[1]
var eggTime = listEggs[2]
println("달걀의 정보는 ${eggs} 입니다.")
println("리스트 달걀의 정보는 ${listEggs} 입니다.")
println("첫번째 달걀의 종류는 ${firstEgg} 입니다.")
println("두번째 달걀의 종류는 ${secondEgg} 입니다.")
println("달걀은 ${eggTime}에 나왔습니다.")
}
class Chicken {
fun getTwoEggs(): Pair<String, String> {
var eggs = Pair("달걀", "맥반석")
return eggs
}
fun getThreeEggs(): Triple<String, String, Int> {
var eggs = Triple("달걀", "맥반석", 20230101)
return eggs
}
}
let function
의 활용it
으로 자신의 객체를 전달하고 수행된 결과를 반환해요 var strNum = "10"
var result = strNum?.let {
// 중괄호 안에서는 it으로 활용함
Integer.parseInt(it)
}
println(result!!+1)
with function
의 활용this
로 자신의 객체를 전달하고 코드를 수행해요 var alphabets = "abcd"
with(alphabets) {
// var result = this.subSequence(0,2)
var result = subSequence(0,2)
println(result)
}
also function
의 활용it
으로 자신의 객체를 전달하고 객체를 반환해줘요apply
와 함께 자주 사용해요fun main() {
var student = Student("참새", 10)
var result = student?.also {
it.age = 50
}
result?.displayInfo()
student.displayInfo()
}
class Student(name: String, age: Int) {
var name: String
var age: Int
init {
this.name = name
this.age = age
}
fun displayInfo() {
println("이름은 ${name} 입니다")
println("나이는 ${age} 입니다")
}
}
fun main() {
fun Student.getGrade() = println("학생의 등급은 ${this.grade} 입니다")
var student = Student("참새", 10, "A+")
student.displayInfo()
student.getGrade()
}
class Student(name: String, age: Int, grade: String) {
var name: String
var age: Int
var grade: String
init {
this.name = name
this.age = age
this.grade = grade
}
fun displayInfo() {
println("이름은 ${name} 입니다")
println("나이는 ${age} 입니다")
}
}
getGrade() -> 확장함수
if(a in b){}
if(a is b){}
프로세스 바탕화면에 더블클릭해서 실행을한다 -> 프로세스 실행됨
동시에 실행한다 -> 하나의 cpu자원 경쟁
코틀린에서 코루틴 쓸땐 외부 라이브러리 모듈 추가해야됨
하드웨어 자원의 효율적인 할당을 가능하게함
쓰레드보다 더욱 가볍게 사용 구글에서 적극 권장
launch
와 async
빌더를 가장 많이 사용함없는
코루틴 빌더있는
코루틴GlobalScope
: 앱이 실행된 이후 계속 수행되어야 할때CoroutineScope
: 필요할때만 생성, 사용 후 정리왜? 쓰레드보다 코루틴이 더 경량화된 개념인데
하나의 쓰레드 안에서 여러개 코루틴을 작동하기위해
Dispatchers.Main
: UI와 상호작용하기 위한 메인쓰레드Dispatchers.IO
: 네트워크나 디스크 I/O작업에 최적화 되어있는 쓰레드Dispatchers.Default
: 기본적으로 CPU최적화 되어있는 쓰레드안드로이드에서는 특히 Dispatcher간의 변환을 해야하는 작업을 고려해야해요
코루틴의 정의
fun main(args: Array<String>) {
println("메인쓰레드 시작")
var job = GlobalScope.launch {
delay(3000)
println("여기는 코루틴...")
}
println("메인쓰레드 종료")
}
안드로이드는 앱이 항상켜져 있어서 사용가능
JVM에선 메인쓰레드가 종료되니 결과 못보긴함
fun main(args: Array<String>) {
println("메인쓰레드 시작")
var job = GlobalScope.launch {
delay(3000)
println("여기는 코루틴...")
}
runBlocking {
job.join()
}
println("메인쓰레드 종료")
}
join을 쓰면 job코루틴 끝날때까지 기다려야함
fun main(args: Array<String>) {
println("메인쓰레드 시작")
var job = CoroutineScope(Dispatchers.Default).launch {
delay(3000)
println("여기는 코루틴...")
}
runBlocking {
job.join()
}
println("메인쓰레드 종료")
job.cancel() //코루틴 스코프라 사용후 정리
}
println("메인쓰레드 시작")
var job = CoroutineScope(Dispatchers.Default).launch {
var fileDownloadCoroutine = async(Dispatchers.IO) {
delay(10000)
"파일 다운로드 완료"
}
var databaseConnectCoroutine = async(Dispatchers.IO) {
delay(5000)
"데이터베이스 연결 완료"
}
println("${fileDownloadCoroutine.await()}")
println("${databaseConnectCoroutine.await()}")
}
runBlocking {
job.join()
}
println("메인쓰레드 종료")
job.cancel()
데이터 가져오고 넣는행위하기위해 적합한 Dispatchers.IO
결과값을 리턴받아야하기 때문에 await은 일시중단이 가능한 코루틴에서 실행가능
💡 동시성 프로그래밍을 다시 정리할게요
heap 메모리
💡 쓰레드와 코루틴의 차이를 정리할게요
쓰레드
작업 하나하나의 단위 : Thread
동시성 보장 수단 : Context Switching
- 운영체제 커널에 의한 Context Switching 을 통해 동시성을 보장해요
- 블로킹 (Blocking)
- Thread A가 Thread B 의 결과를 기다리고 있어요
- 이 때, Thread A는 블로킹 상태라고 할 수 있어요
- A는 Thread B 의 결과가 나올 때 까지 해당 자원을 사용하지 못해요
Thread A가 Task 1을 수행하는 동안 Task 2 의 결과가 필요하면 Thread B를 호출해요
이때 Thread A는 블로킹 되고 Thread B로 프로세스간에 스위칭이 일어나 Task 2을 수행해요
Task 2가 완료되면 Thead A로 다시 스위칭해서 결과 값을 Task 1에게 반환해요
이때 Task 3, Task 4는 A, B작업이 진행되는 도중에 멈추지 않고 각각 동시에 실행되게 되요
이때 컴퓨터 운영체제 입장에서는 각 Task를 쪼개서 얼마나 수행할지가 중요하겠죠?
그래서 어떤 쓰레드를 먼저 실행해야할지 결정하는행위를 스케쥴링이라고 해요
이러한 행위를 통해 동시성을 보장해요
코루틴
소스 코드를 통해 Switching 시점을 마음대로 정해요 (OS는 관여하지 않아요)
Suspend (Non-Blocking)
- Object 1이 Object 2의 결과를 기다릴 때 Object 1의 상태는 Suspend로 바뀌어요
- 그래도 Object 1을 수행하던 **Thread는 그대로 유효해요**
- 그래서 Object 2도 Object 1과 동일한 Thread에서 실행되어요
요약