Christmas Pikachu 제네릭, Isolate
개발일지/Dart

제네릭, Isolate

ZI_CO 2022. 11. 8.

제네릭

제네릭 프로그래밍은 타입 매개 변수 (T)를 통해

타입에 대한 유연한 대처를 가능하게 한다.

다트 컬렉션에서 많이 사용 된다.

import 'main_06.dart';

/// Dart Generic
/// 제네릭 프로그래밍은 타입 매개 변수(T)를 통해 타입에 대한 유연한 대처를 가능케 한다.
/// 다트 컬렉션에서 많이 사용 되어 진다.
///

void main() {

  Powder powder = Powder();
  Plastic plastic = Plastic();

  GenericPrinter<Powder> printer1 = GenericPrinter();
  GenericPrinter<Plastic> printer2 = GenericPrinter();

  printer1.setMaterial(powder);
  printer2.setMaterial(plastic);

  print(printer1);
  print(printer2);

}

class GenericPrinter<T> {
  late T material;

  // 지연 변수(late) 
  // : 컴파일 시점에 처리가 되는 것이 아니라 뒤늦게 들어와도 된다는 변수

  T getMaterial() {
    return material;
  }

  void setMaterial(T material) {
    this.material = material;
  }

  @override
  String toString() {
    return 'GenericPrinter{material: $material}';
  }
}

 

 

 

 

제네릭 - T extends

T에 무작위 클래스가 들어갈 수 없게 특정 클래스를 상속받은 클래스로만 한정한다.

void main () {
  GenericPrinter<Plastic> printer1 = GenericPrinter();
  GenericPrinter<Powder> printer2 = GenericPrinter();

  // GenericPrinter<Water> printer2 = GenericPrinter();
  // 사용불가! extends한 Material들만 넣을 수 있다.

}

class GenericPrinter<T extends Material> {
late T material;

T getMaterial(){
  return material;
}

void setMaterial (T material){
  this.material = material;
}
}

abstract class Material {
  void doPrinting();
}
class Powder extends Material {
  @override
  void doPrinting() {
  }

}

class Plastic extends Material{
  @override
  void doPrinting() {
  }

}

class Water{

}

 

 

 

 

 

 

Isolate

일반적으로 프로그래밍은 순차적으로 작업을 처리한다.

즉, 하나의 작업을 요청한 후 그 작업이 끝나면 다음 작업으로 넘어간다.

이런 경우 처리시간이 긴 작업 (특히 ui와 관련된 상황)을 만나면

사용자는 프로그램이 멈춘 것 처럼 느낄 수 있다.

이러한 문제는 비동기 프로그래밍

(Asynchronous Programming)으로 해결 할 수 있다.

* 비동기 프로그래밍은 요청한 작업의 결과를 기다리지 않고

바로 다음 작업으로 넘어감으로써 프로그램의 실행을 멈추지 않는다.

비동기는 동시성 (Concurrency)이나 병렬(Parallel)과 비교군이

될 수 없는 완전히 다른 개념이다.

다트에서는 future, stream API를 통해서 자체적으로

비동기 프로그래밍을 지원하고 있다.

★ Isolate - 격리하다는 의미

-Isolate는 다트의 모든 코드가 실행되는 공간이다.

싱글 스레드를 가지고 있고, 이벤트 루프를 통해 작업을 처리한다.

기본 Isolate인 main Isolate는 런타임에 생성 된다.

★ 새로운 Isolate 생성하기

: spawn 함수를 사용하면 된다.

- Dart는 일급 객체를 지원하는 언어라서

매개변수로 함수를 전달 할 수 있다 ! (자바는 불가능)

-Isolate는 cpu가 처리하므로 우리가 손을 델 수가 없으며,

순서가 보장되지 않는다

-shared resource(공유자원) 를 발생 시키지 않는다.

void main () {
  print(".....................main isolate.....................");
  Isolate.spawn(doNewJobIsolate,"1번 너가 할 일 청소");
  Isolate.spawn(doNewJobIsolate,"2번 너는 잠자기");
  Isolate.spawn(doNewJobIsolate,"3번 너는 집에 가기");
} 

doNewJobIsolate(var taskContent) {
  print('>>> $taskContent <<<');
}

 

 

 

 

 

 

ReveivePort & SendPort

Isolate 사이의 커뮤니케이션은 receivePort와 sendPort로 이루어진다.

모든 Isolate는 자신만의 receivePort를 생성 할 수 있고,

또는 multiple receivePort도 가능하다.

-> subIsolateProcess 메서드로 receivePort 안에있는

sendPort를 가지고 와야한다.

import 'dart:isolate';

void main (){

  ReceivePort receivePort = ReceivePort();
  receivePort.listen((message) {
    print("여기는 바로 수행된 것이 아니라 message 가 들어오면 동작 되는거야!");
    print("runtimeType check");
    print(message.runtimeType);
    print('들어온 메시지 확인 : ${message}');
  });

  print("main isolate 작업을 하고 있어요  ~ ~ ~ ~ ~");
  // 다른 Isolate 생성하고 작업 요청
  subIsolateProcess(receivePort.sendPort);
  //sendPort는 reveivePort 안에 있음 !
}

subIsolateProcess(SendPort sendPort){
  Isolate.spawn((sendPort) {
    for(var i=1; i <10; i++){
      print("i : $i 동작 수행");
    }
    sendPort.send("다른 작업자의 for문 동작 끝났어");
  }, sendPort);
}

댓글