android 장점 - 처리기 대 AsyncTask 대 스레드




6 Answers

Vogella 사이트의 Handlers, AsyncTask 및 Loaders사용한 Android 백그라운드 처리 자습서에서 다음과 같이 설명합니다.

Handler 클래스는 스레드에 등록하는 데 사용할 수 Handler 스레드에 데이터를 보내기위한 간단한 채널을 제공합니다.

AsyncTask 클래스는 백그라운드 프로세스 생성과 주 스레드와의 동기화를 캡슐화합니다. 또한 실행중인 작업의보고 진행을 지원합니다.

그리고 Thread 는 기본적으로 개발자가 다음과 같은 단점을 가지고 사용할 수있는 멀티 스레딩의 핵심 요소입니다.

자바 쓰레드를 사용한다면 자신의 코드에서 다음과 같은 요구 사항을 처리해야한다.

  • 결과를 사용자 인터페이스에 게시하는 경우 주 스레드와 동기화
  • 스레드 취소 기본값 없음
  • 기본 스레드 풀링 없음
  • Android에서 구성 변경을 처리 할 때 기본값이 없습니다.

그리고 AsyncTask 에 관해서는 documentation 다음과 같이 AsyncTask 있다.

AsyncTask 사용하면 UI 스레드를 적절하고 쉽게 사용할 수 있습니다. 이 클래스는 백그라운드 작업을 수행하고 스레드 및 / 또는 핸들러를 조작하지 않고도 UI 스레드에서 결과를 게시 할 수있게합니다.

AsyncTaskThreadHandler 주위의 도우미 클래스로 설계되었으며 일반 스레딩 프레임 워크를 구성하지 않습니다. AsyncTasks는 짧은 작업 (최대 몇 초)에 이상적으로 사용되어야합니다. 오랜 기간 동안 스레드를 계속 실행해야하는 경우 java.util.concurrent 패키지에서 제공하는 다양한 API (예 : Executor, ThreadPoolExecutor 및 FutureTask.

2015 년 5 월 업데이트 : 이 주제를 다루는 우수한 강의 시리즈를 발견했습니다.

Douglas Schmidt 강의 안드로이드 동시성 및 동기화

이것은 YouTube첫 번째 강연 동영상입니다.

이 모든 것은 CS 282 (2013) 의 일부입니다 : Vanderbilt University 에서 Android 용 시스템 프로그래밍 . 다음은 YouTube 재생 목록입니다.

더글라스 슈미트 (Douglas Schmidt)는 우수한 강사로 보인다.

중요 사항 : AsyncTask 를 사용하여 스레드 문제를 해결하려는 경우 ReactiveX/RxAndroid 에서 가능한 더 적합한 프로그래밍 패턴을 확인 해야합니다. 개요를 얻기위한 훌륭한 자료는 예제를 통해 Android 용 RxJava 2 학습 입니다.

method onpreexecute

Android에서 Handlers , AsyncTaskThreads 의 차이점에 대해 약간 혼란스러워합니다. 나는 꽤 많은 블로그와 질문을 에서 읽었다.

Handler 는 UI와 통신 할 수 있도록 해주는 백그라운드 스레드입니다. 진행 바를 업데이트하는 것은 Handler 를 통해 수행되어야합니다. 핸들러를 사용하면 MessagingQueues 의 이점이 있으므로 메시지를 예약하거나 여러 UI 요소를 업데이트하거나 반복되는 작업을 원할 경우 유용합니다.

AsyncTaskHandler 사용하지만 UI 스레드에서 실행되지 않기 때문에 AsyncTask 유사합니다. 따라서 웹 서비스를 가져 오는 것과 같이 데이터를 가져 오는 것이 좋습니다. 나중에 UI와 상호 작용할 수 있습니다.

Thread 는 UI와 상호 작용할 수 없으며 "기본"스레딩을 제공하고 AsyncTask 모든 추상화를 놓 AsyncTask .

그러나 서비스에서 소켓 연결을 실행하고 싶습니다. 이 핸들러 또는 스레드 또는 AsyncTask 에서 실행해야합니까? UI 상호 작용은 전혀 필요하지 않습니다. 내가 사용하는 성능면에서 차이가 있습니까?

한편 documentation 가 크게 개선되었습니다.




깊게 본 후 곧장 나아질 것입니다.

AsyncTask :

그것은 자바 스레드 모델에 대해 아무 것도 모른 채 스레드를 사용하는 간단한 방법입니다. AsyncTask 는 작업자 스레드와 주 스레드에 대한 다양한 콜백을 제공합니다.

다음과 같은 작은 대기 작업에 사용합니다.

  1. 웹 서비스에서 일부 데이터를 가져 와서 레이아웃을 표시합니다.
  2. 데이터베이스 쿼리.
  3. 실행 작업이 절대로 결코 중첩되지 않는다는 것을 알게되면.

Handler :

안드로이드에 응용 프로그램을 설치하면 MAIN UI Thread라는 해당 응용 프로그램 용 스레드가 생성됩니다. 모든 액티비티는 해당 스레드 내에서 실행됩니다. 안드로이드 단일 스레드 모델 규칙에 따라 우리는 UI 요소 (비트 맵, 텍스트 뷰 등)에 해당 액티비티 내에 정의 된 다른 스레드에 직접 액세스 할 수 없습니다.

핸들러를 사용하면 다른 백그라운드 스레드의 UI 스레드와 다시 통신 할 수 있습니다. 안드로이드는 다른 스레드가 UI 스레드와 직접 통신 할 수 없으므로 안드로이드에서 유용합니다. 처리기는 스레드의 MessageQueue와 관련된 Message 및 Runnable 객체를 보내고 처리 할 수 ​​있습니다. 각 Handler 인스턴스는 단일 스레드 및 해당 스레드의 메시지 큐와 연관됩니다. 새로운 Handler가 작성되면 (자), 작성 중의 thread의 thread / 메세지 큐에 바인드됩니다.

다음에 가장 적합합니다.

  1. 메시지 큐잉을 할 수 있습니다.
  2. 메시지 스케줄링.

Thread :

이제 스레드에 대해 이야기 할 시간입니다.

Thread는 AsyncTaskHandler 의 부모입니다. 둘 다 내부적으로 스레드를 사용하므로 AsyncTaskHandler 와 같은 자체 스레드 모델을 만들 수도 있지만 Java의 다중 스레드 구현에 대한 지식이 필요합니다.




Thread

Android는 표준 자바 스레드를 지원합니다. 표준 스레드와 " java.util.concurrent "패키지의 도구를 사용하여 작업을 백그라운드에 넣을 수 있습니다. 유일한 제한은 백그라운드 프로세스에서 UI를 직접 업데이트 할 수 없다는 것입니다.

백그라운드 작업에서 UI를 업데이트해야하는 경우 일부 Android 관련 클래스를 사용해야합니다. 이 클래스 또는 " AsyncTask "클래스에는 " android.os.Handler "클래스를 사용할 수 있습니다.

Handler

" Handler "클래스는 UI를 업데이트 할 수 있습니다. 핸들은 메시지를 수신하고 실행 가능한 메소드를 제공합니다. 핸들러를 사용하려면 핸들러를 서브 클래스 화하고 handleMessage() 를 대체하여 메시지를 처리해야합니다. Runable 을 처리하려면 post(); 메소드를 사용할 수 있습니다 post(); 액티비티에는 하나의 핸들러 인스턴스 만 있으면됩니다.

스레드는 sendMessage(Message msg) 또는 sendEmptyMessage 메소드를 통해 메시지를 게시 할 수 있습니다.

documentation

백그라운드에서 수행 할 수있는 컨텐츠를 다운로드하거나 작업을 수행해야하는 Activity 이있는 경우 AsyncTask 사용하면 반응이 빠른 사용자 인터페이스를 유지하고 해당 작업의 진행 상황을 사용자에게 게시 할 수 있습니다.

자세한 내용은이 링크를 참조하십시오.

http://mobisys.in/blog/2012/01/android-threads-handlers-and-asynctask-tutorial/

http://www.slideshare.net/HoangNgoBuu/android-thread-handler-and-asynctask




Thread :

UI 스레드에 영향을 미치지 않으면 서 장기 실행 백그라운드 작업에 새 Thread 를 사용할 수 있습니다. 자바 스레드에서 UI 스레드를 업데이트 할 수 없습니다.

일반 Thread 는 안드로이드 아키텍처에별로 도움이되지 않기 때문에 스레딩을위한 도우미 클래스가 도입되었습니다.

스레딩 성능 문서 페이지에서 쿼리에 대한 답변을 찾을 수 있습니다.

Handler :

Handler 사용하면 스레드의 MessageQueue 와 관련된 Message 및 Runnable 객체를 보내고 처리 할 수 ​​있습니다. 각 Handler 인스턴스는 단일 스레드 및 해당 스레드의 메시지 큐와 연관됩니다.

Handler 에는 두 가지 주요 용도가 있습니다.

  1. 미래의 어떤 시점에서 실행될 메시지와 실행 파일을 예약하려면 다음을 수행하십시오.

  2. 자신의 스레드와 다른 스레드에서 수행 할 작업을 큐에 추가하려면.

documentation :

AsyncTask 사용하면 UI 스레드를 적절하고 쉽게 사용할 수 있습니다. 이 클래스를 사용하면 스레드 및 / 또는 핸들러를 조작하지 않고도 UI 스레드에서 백그라운드 작업을 수행하고 결과를 게시 할 수 있습니다.

단점 :

  1. 기본적으로 응용 프로그램은 작성한 모든 AsyncTask 객체를 단일 스레드로 푸시합니다. 따라서 직렬 방식으로 실행되며 주 스레드와 마찬가지로 특히 긴 작업 패킷이 대기열을 차단할 수 있습니다. 이러한 이유 때문에 AsyncTask를 사용하여 5ms 보다 짧은 작업 항목을 처리하십시오.

  2. AsyncTask 개체는 암시 적 참조 문제의 가장 일반적인 범죄자이기도합니다. AsyncTask 객체는 명시 적 참조와 관련된 위험을 나타냅니다.

HandlerThread :

5ms 작업 부하에 사용해야하는 AsyncTask와는 달리 더 오래 실행되는 스레드에서 작업 블록을 실행하는 데보다 전통적인 접근 방식이 필요하며 수동으로 해당 워크 플로를 관리 할 수있는 몇 가지 기능 이 필요할 수 있습니다. 핸들러 쓰레드는 사실 큐에서 작업하고 그것을 처리하는 장기 실행 쓰레드입니다.

ThreadPoolExecutor :

이 클래스는 스레드 그룹 생성을 관리하고 우선 순위를 설정하며 해당 스레드간에 작업이 분산되는 방식을 관리합니다. 작업 부하가 증가하거나 감소하면 클래스는 작업 부하를 조정하기 위해 더 많은 스레드를 돌리거나 파괴합니다.

작업 부하가 더 HandlerThread 하나의 HandlerThread 만으로 충분하지 않다면 ThreadPoolExecutor

그러나 서비스에서 소켓 연결을 실행하고 싶습니다. 이 핸들러 또는 스레드 또는 AsyncTask에서 실행해야합니까? UI 상호 작용은 전혀 필요하지 않습니다. 내가 사용하는 성능면에서 차이가 있습니까?

UI 상호 작용이 필요하지 않으므로 AsyncTask 로 이동할 수 없습니다. 일반 스레드는 그리 유용하지 않으므로 HandlerThread 가 가장 좋습니다. 소켓 연결을 유지해야하기 때문에 메인 쓰레드의 Handler는 전혀 쓸모가 없다. HandlerThread 만들고 HandlerThread 루퍼에서 Handler 를 가져 HandlerThread .

 HandlerThread handlerThread = new HandlerThread("SocketOperation");
 handlerThread.start();
 Handler requestHandler = new Handler(handlerThread.getLooper());
 requestHandler.post(myRunnable); // where myRunnable is your Runnable object. 

다시 UI 스레드와 통신하려면 응답을 처리하기 위해 하나 이상의 Handler를 사용할 수 있습니다.

final Handler responseHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            //txtView.setText((String) msg.obj);
            Toast.makeText(MainActivity.this,
                    "Foreground task is completed:"+(String)msg.obj,
                    Toast.LENGTH_LONG)
                    .show();
        }
    };

당신의 Runnable , 당신은

responseHandler.sendMessage(msg);

구현에 대한 자세한 내용은 다음을 참조하십시오.

Android : 토스트의 스레드




여기에 예를 들어 질문을 해봅시다.) - MyImageSearch [텍스트 편집 / 검색 버튼 / 격자보기가 포함 된 주요 활동 화면의 이미지를 참조하십시오]

MyImageSearch에 대한 설명 - 사용자가 편집 텍스트 필드에 대한 세부 정보를 입력하고 검색 버튼을 클릭하면 flickr에서 제공하는 웹 서비스를 통해 인터넷에서 이미지를 검색합니다 (여기에 등록하면 키 / 비밀 토큰을 얻을 수 있습니다) - 검색을 위해 우리는 그리드 뷰를로드하는 데 사용할 개별 이미지의 url을 포함하는 HTTP 요청과 JSON 데이터를 응답으로 보냅니다.

내 구현 - 주요 활동에서 AsyncTask를 확장하여 doInBackGround 메서드에서 HTTP 요청을 보내고 JSON 응답을 가져오고 FlickrAdapter를 통해 GridView를 업데이트하는 데 사용할 FlickrItems의 로컬 ArrayList를 업데이트하는 내부 클래스를 정의합니다. (BaseAdapter를 확장) AsyncTask의 onPostExecute ()에서 adapter.notifyDataSetChanged ()를 호출하여 눈금보기를 다시로드하십시오. 여기에서 HTTP 요청은 AsyncTask를 통해 수행했기 때문에 차단 요청입니다. 그리고 어댑터의 항목을 캐싱하여 성능을 높이거나 SDCard에 저장할 수 있습니다. FlickrAdapter에서 내가 팽창시킬 그리드는 내 구현에서 progressbar와 이미지 뷰를 포함합니다. 아래에서 내가 사용했던 mainActivity 코드를 찾을 수 있습니다.

질문에 대한 답변 - 개별 이미지를 가져 오는 데 필요한 JSON 데이터를 얻은 후에는 처리기 또는 스레드 또는 AsyncTask를 통해 백그라운드에서 이미지를 가져 오는 논리를 구현할 수 있습니다. 우리가 다운로드 한 내 이미지는 UI / 주 스레드에 표시되어야하므로 단순히 스레드를 컨텍스트에 액세스 할 수 없기 때문에 단순히 사용할 수는 없습니다. FlickrAdapter에서 내가 생각할 수있는 선택 사항은 다음과 같습니다.

  • 선택 1 : LooperThread [스레드 늘이기] 만들기 -이 스레드를 열어서 한 스레드에서 이미지를 계속 다운로드하십시오 [looper.loop ()]
  • 선택 2 : 스레드 풀을 사용하고 내 ImageView에 대한 참조가 포함 된 myHandler를 통해 실행 파일을 게시하지만 그리드보기의 뷰가 재활용되므로 인덱스 4의 이미지가 인덱스 9에 표시되는 문제가 다시 발생할 수 있습니다. 더 많은 시간을 가져라]
  • 선택 3 [내가 사용한 방법] : Thread Pool을 사용하고 ImageView의 인덱스와 ImageView와 관련된 데이터를 포함하는 myHandler에게 메시지를 보냅니다. handleMessage ()를 수행하는 동안 currentIndex가 인덱스와 일치하는 경우에만 ImageView를 업데이트합니다. 우리가 다운로드하려고 시도한 이미지.
  • 선택 4 : 백그라운드에서 이미지를 다운로드하려면 AsyncTask를 사용합니다. 그러나 여기서는 스레드 풀에서 원하는 스레드 수에 액세스 할 수 없으며 다른 Android 버전에 따라 달라집니다. 그러나 선택 3에서는 의식적인 결정을 내릴 수 있습니다. 스레드 풀 크기는 사용중인 장치 구성에 따라 다릅니다.

여기 소스 코드 :

public class MainActivity extends ActionBarActivity {

    GridView imageGridView;
    ArrayList<FlickrItem> items = new ArrayList<FlickrItem>();
    FlickrAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageGridView = (GridView) findViewById(R.id.gridView1);
        adapter = new FlickrAdapter(this, items);
        imageGridView.setAdapter(adapter);
    }

    // To avoid a memory leak on configuration change making it a inner class
    class FlickrDownloader extends AsyncTask<Void, Void, Void> {



        @Override
        protected Void doInBackground(Void... params) {
            FlickrGetter getter = new FlickrGetter();

            ArrayList<FlickrItem> newItems = getter.fetchItems();

            // clear the existing array
            items.clear();

            // add the new items to the array
            items.addAll(newItems);

            // is this correct ? - Wrong rebuilding the list view and should not be done in background
            //adapter.notifyDataSetChanged();

            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);

            adapter.notifyDataSetChanged();
        }

    }

    public void search(View view) {
        // get the flickr data
        FlickrDownloader downloader = new FlickrDownloader();
        downloader.execute();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

내 대답은 오랫동안 미세한 부분을 이해하는 데 도움이되기를 바랍니다.




Handler - 스레드 간의 통신 매체입니다. 안드로이드에서는 주로 핸들러를 통해 메시지를 작성 및 전송하여 주 스레드와 통신하는 데 사용됩니다.

AsyncTask - 백그라운드 스레드에서 장기 실행 응용 프로그램을 수행하는 데 사용됩니다. n AsyncTask 를 사용하면 백그라운드 스레드에서 작업을 수행하고 응용 프로그램의 기본 스레드에서 결과를 얻을 수 있습니다.

Thread - 동시성 및 최대 CPU 사용률을 달성하기위한 경량 프로세스입니다. 안드로이드에서는 스레드를 사용하여 앱의 UI를 터치하지 않는 활동을 수행 할 수 있습니다.




Related

android multithreading android-asynctask android-handler