Java - AsyncTask와 Thread

프로그래밍/Android 2022. 6. 10. 21:26

AsyncTask

  1. AsyncTask 객체는 항상 UI Thread에서 생성해야 하는 제약이 있다. 이는 Backend 에서 AsyncTask를 사용하기 어렵다는 것을 의미한다. (API 16이상에서는 자유롭게 사용하도록 수정됨)
  2. execute를 항상 UI thread에서 호출해야 한다.
  3. 수동으로 override 함수인 onPreExecute, onPostExecute, doInBackground.. 등을 호출하면 안된다.
  4. Task는 한 번만 실행할 수 있고 재 사용이 불가하다.
  5. Activity가 종료 되어도 별도의 처리가 없으면 Task가 사라지지 않는다.
  6. AsyncTask의 기본 처리 작업 갯수는 1개이다.

AsyncTask는 단점이 너무 많다. -> 안쓰는 걸로 하자.

 

Thread

  1. Thread의 사용방법은 2가지 인데…
  2. Thread를 상속받은 class를 만들어서 run()을 override해서 사용하는 방법
 
    class MyThread extends Thread {
        MyThread() {
        }
        public void run() {
            // TODO : thread running codes.
        }
    }

    MyThread nt = new MyThread() ;
    nt.start() ;

3. Runnable interface를 implementation 해서 Thread에 주입하여 사용하는 방법

 
    class MyRunnable implements Runnable {
        MyRunnable() {
        }

        public void run() {
            // TODO : thread running codes.
        }
    }

    MyRunnable nr = My NewRunnable() ;
    Thread t = new Thread(nr) ;
    t.start() ;

위 두가지 방법은 성능 면에서는 차이가 없지만 Runnable을 사용하면…

1. java가 다중 상속이 안되어 Thread class구현에 한계가 있는데 runnable 을 상속받으면 가능하다.

2. 반대로 Thread class의 원래 기능을 override해야 한다면 Thread를 상속해 사용해야 한다.

 

따라서 일반적인 경우에 1의 경우처럼 runnable을 사용하고 Thread의 고유 기능을 override해야 하는 경우는 Thread를 상속해 사용하도록 하자.

 

 

그럼 Thread의 결과를 UI thread에서 사용하려면?

아래 방법은 어떨까?

MyMainClass가 내부에 runnable을 구현하고 Thread나 Executor에 넘겨주어 작업이 끝나면

LiveData에 결과를 넣어주는 것이다. Thread 대신 Executor를 사용해 보자.

 
class MyMainClass {
...
    private LiveData ldata;
...
    funcA() // 일반 Thread를 사용한 예
    {
        MyRunnable nr = My NewRunnable() ;
        Thread t = new Thread(nr) ;
        t.start() ;
    }
    funcB() // ExecutorService를 이용한 예
    {
        MyRunnable nr = My NewRunnable() ;
        ExecutorService mExecutorService = Executors.newFixedThreadPool(100);
        mExecutorService.execute(nr);
    }
    
    handleResult(result) {
       ldata = result;
    }
    class MyRunnable implements Runnable {
        MyRunnable() {
        }

        public void run() {
            // TODO : thread running codes.
            handleResult(result);
        }
    }
}

Multi-Thread의 어려운 점은 여러개의 Thread가 동시에 불렸을때의 관리이다.

위 code에서 ExecutorService를 통해 여러개의 Thread가 동시에 불린다면…. 어떤 thread가 동작 중이고

모든 thread가 종료 되었는지 확인하는 것이 어렵다. 이를 위해 callablefuture를 사용하면 된다.

사용방법은

  1. runnable에서 handleResult를 직접 처리하지 않고 callble에서 처리하도록 한다.
  2. ExecutorService에 각각의 작업에 대한 callable을 제공하면 각각의 future를 얻을 수 있다.
  3. future.get 을 수행하면 해당 작업이 끝날때 까지 대기한다. blocking function이므로 되도록 UI thread에서는 바로 사용하지 않도록 한다. 대신 runnable안의 run에서 사용한다.
  4. run()안에서 future.get으로 대기하다가 callable이 발생 시키는 exception을 처리할 수 있다.
 
class MyMainClass {
...
    private LiveData ldata;
...
    funcA() // 일반 Thread를 사용한 예
    {
        MyRunnable nr = My NewRunnable() ;
        Thread t = new Thread(nr) ;
        t.start() ;
    }
    funcB() // ExecutorService를 이용한 예
    {
        MyRunnable nr = My NewRunnable() ;
        ExecutorService mExecutorService = Executors.newFixedThreadPool(100);
        mExecutorService.execute(nr);
    }
    class MyRunnable implements Runnable {
        MyRunnable() {
        }

        public void run() {
            // TODO : thread running codes.
            handleResult(result);
        }
    }
    
    funcC() // ExecutorService, callable, future를 이용한 예
    {
        Callable<Boolean> callable = new Callable<Boolean>() {
            @override
            public Boolean call() throw Exception {
                return handleResult(result);
            }
        }
        MyFutureRunnable nr = My NewFutureRunnable() ;
        ExecutorService mExecutorService = Executors.newFixedThreadPool(100);
        Future<Boolean> future = mExecutorService..submit(callable);
        mExecutorService.execute(nr);
    }
    class MyFutureRunnable implements Runnable {
        public MyFutureRunnable(Future future) {
        }
        public void run() {
          try {
              future.get();
          } catch(InterruptedException e) {
              Thread.currentThread().interrupt();
              future.cancel(true);
          } catch(Exception e) {
          }
        }
    }
    handleResult(result) {
       ldata = result;
    }

}
728x90
반응형

'프로그래밍 > Android' 카테고리의 다른 글

구글이 추천하는 Android Architecture  (0) 2022.06.10
admin