[android] 처리기 대 AsyncTask 대 스레드


Answers

AsyncTaskHandler 의 소스 코드를 보면 코드가 순수하게 Java로 작성된 것을 볼 수 있습니다. (물론 예외가 있지만 중요한 것은 아닙니다.)

AsyncTask 또는 Handler 에는 마법이 없습니다. 그들은 개발자로서 당신의 일을 더 쉽게 만듭니다.

예를 들어, 프로그램 A가 메소드 A ()를 호출하면 메소드 A ()가 프로그램 A와 다른 스레드에서 실행될 수 있습니다. 다음을 사용하여 메소드 A ()를 쉽게 확인할 수 있습니다.

Thread t = Thread.currentThread();    
int id = t.getId();

왜 새 스레드를 사용해야합니까? 당신은 그것을 위해 구글 수 있습니다. 많은 많은 이유.

그렇다면 Thread , AsyncTaskHandler 의 차이점은 무엇입니까?

AsyncTaskHandler 는 Java로 작성되며 (내부적으로 Thread 를 사용함) Handler 또는 AsyncTask 수행 할 수있는 모든 작업을 Thread 사용하여 AsyncTask 할 수도 있습니다.

HandlerAsyncTask 실제로 무엇을 도와 줄 수 있습니까?

가장 명백한 이유는 호출자 스레드와 작업자 스레드 간의 통신입니다. ( 호출자 스레드 : 작업자 스레드를 호출하여 작업을 수행하는 스레드. 호출자 스레드는 UI 스레드 일 필요는 없습니다.) 물론 다른 방법으로 두 스레드간에 통신 할 수 있지만 스레드 안전 문제로 인해 많은 단점 (및 위험)이 있습니다.

그래서 HandlerAsyncTask 를 사용해야합니다. 그들은 당신을 위해 대부분의 작업을 수행합니다. 어떤 방법으로 오버라이드해야하는지 알 필요가 있습니다.

HandlerAsyncTask 의 차이점은 다음과 같습니다. 호출자 스레드UI 스레드 일AsyncTask 사용합니다. 이것은 안드로이드 문서가 말하는 것입니다 :

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

두 가지 점을 강조하고 싶습니다.

1) UI 스레드를 쉽게 사용할 수 있습니다 (호출자 스레드가 UI 스레드 일 때 사용).

2) 핸들러를 조작 할 필요가 없습니다. (의미 : AsyncTask 대신 Handler를 사용할 수 있지만 AsyncTask는 더 쉬운 옵션입니다.)

이 게시물에는 아직 말하지 않은 많은 것들이 있습니다. 예를 들어 UI 스레드 란 무엇입니까? 왜 더 쉬운가? 당신은 각 종류의 뒤에 어떤 방법을 알고 그것을 사용해야합니다, 당신은 완전히 이해할 것입니다. 왜 ..

@ : Android 문서를 읽으면 다음과 같이 표시됩니다.

처리기를 사용하면 스레드의 MessageQueue와 관련된 Message 및 Runnable 객체를 보내고 처리 할 수 ​​있습니다.

그들은 처음에는 이상하게 보일 수 있습니다. 각 스레드가 할 일 목록과 같은 각 메시지 큐를 가지고 있다는 것을 이해하면 스레드는 각 메시지를 가져 와서 메시지 대기열이 비어있을 때까지 (작업을 마치고 잠자리에 드는 것처럼) 수행합니다. 따라서 Handler 통신 할 때 호출자 스레드에 메시지를 보내면 처리 대기 상태가됩니다. 복잡한? Handler 는 호출자 스레드와 안전하게 통신 할 수 있다는 것을 기억하십시오.

Question

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

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

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

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

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

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




제 생각에는 스레드는 소켓 연결을 수행하는 가장 효율적인 방법은 아니지만 스레드를 실행하는 측면에서 가장 많은 기능을 제공합니다. 경험으로 볼 때 장시간 스레드를 실행하면 장치가 매우 뜨거워지고 리소스가 많이 소모되기 때문입니다. 심지어 단순한 while(true) 전화를 몇 분 안에 데울 것입니다. UI 상호 작용이 중요하지 않다고 말하면 AsyncTask 는 장기 프로세스를 위해 설계되었으므로 아마도 좋은 것입니다. 이것은 그것에 대한 제 의견입니다.

최신 정보

위의 답변을 무시하십시오! 나는 2011 년에 내가 지금보다 안드로이드에 대한 경험이 훨씬 적었을 때이 질문에 답했다. 위의 내 대답은 오해의 소지가 있으며 잘못된 것으로 간주됩니다. 많은 사람들이 저를 바로 잡기 아래에 댓글을 달았 기 때문에 나는 그곳을 떠날 것입니다. 그리고 저는 제 공과를 배웠습니다.

이 스레드에는 훨씬 더 좋은 답변이 있지만 적어도 적절한 대답을 줄 것입니다. 일반 자바 Thread 를 사용할 때 아무런 문제가 없습니다. 그러나 잘못 구현하는 것은 매우 프로세서 집약적 일 수 있기 때문에 구현 방법에 대해 신중해야합니다 (가장 주목할만한 증상은 장치가 과열 될 수 있음). AsyncTask 는 백그라운드에서 실행하려는 대부분의 작업 (디스크 I / O, 네트워크 호출 및 데이터베이스 호출)에 이상적입니다. 그러나 AsyncTask 는 사용자가 앱을 닫거나 기기를 대기 상태로 만든 후에 계속해야하는 긴 프로세스에 사용하면 안됩니다. 대부분의 경우, UI 스레드에 속하지 않는 모든 것이 AsyncTask 에서 처리 될 수 있다고 말할 수 있습니다.




AsyncTask 는 백그라운드 계산을 수행하고 UI 스레드에 결과를 게시하는 데 사용됩니다 (옵션으로 진행률 업데이트가 있음). UI에 관심이 없으므로 Handler 또는 Thread 더 적합 해 보입니다.

Handlerpost 메서드를 사용하여 백그라운드 Thread 생성하고 메시지를 메인 스레드로 다시 전달할 수 있습니다.




앱을 시작하면 코드를 실행하는 프로세스가 생성됩니다. 컴퓨팅 리소스를 효율적으로 사용하기 위해 프로세스 내에서 스레드를 시작할 수 있으므로 여러 작업을 한 번에 실행할 수 있습니다. 따라서 스레드를 사용하면 유휴 시간없이 효율적으로 CPU를 활용하여 효율적인 응용 프로그램을 만들 수 있습니다.

Android에서는 모든 구성 요소가 하나의 호출 된 주 스레드에서 실행됩니다. 안드로이드 시스템 대기열 작업 및 메인 스레드에서 하나씩 그들을 실행합니다. 장기 실행 작업이 실행되면 앱이 응답하지 않게됩니다.

이를 방지하기 위해 작업자 스레드를 만들고 백그라운드 또는 장기 실행 작업을 실행할 수 있습니다.

매니저

안드로이드는 단일 쓰레드 모델을 사용하기 때문에, UI 컴포넌트는 비 쓰레드 (thread-safe)로 만들어 지는데, 이는 생성 된 쓰레드 만이 그것들에 접근해야한다는 것을 의미합니다. 즉, UI 컴포넌트는 메인 쓰레드에서만 업데이트되어야합니다. UI 구성 요소가 주 스레드에서 실행되므로 작업자 스레드에서 실행되는 작업은 UI 구성 요소를 수정할 수 없습니다. 이것은 Handler가 그림을 그리는 곳입니다. Looper의 도움을받는 핸들러는 새로운 스레드 또는 기존 스레드에 연결하여 연결된 스레드에 포함 된 코드를 실행할 수 있습니다.

핸들러는 스레드 간 통신을 가능하게합니다. Handler를 사용하면 백그라운드 스레드가 결과를 보낼 수 있으며 주 스레드에 연결된 핸들러는 주 스레드의 UI 구성 요소를 업데이트 할 수 있습니다.

AsyncTask

Android에서 제공하는 AsyncTask는 백그라운드에서 간단한 작업을 실행하고 백그라운드 스레드에서 메인 스레드로 결과를 쉽게 업데이트 할 수 있도록 스레드와 핸들러를 모두 사용합니다.

예제는 안드로이드 쓰레드, 핸들러, asynctask 및 쓰레드 풀 을 참조하십시오.




public class RequestHandler {

    public String sendPostRequest(String requestURL,
                                  HashMap<String, String> postDataParams) {

        URL url;

        StringBuilder sb = new StringBuilder();
        try {
            url = new URL(requestURL);

            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(15000);
            conn.setConnectTimeout(15000);
            conn.setRequestMethod("POST");
            conn.setDoInput(true);
            conn.setDoOutput(true);


            OutputStream os = conn.getOutputStream();
            BufferedWriter writer = new BufferedWriter(
                    new OutputStreamWriter(os, "UTF-8"));
            writer.write(getPostDataString(postDataParams));

            writer.flush();
            writer.close();
            os.close();
            int responseCode = conn.getResponseCode();

            if (responseCode == HttpsURLConnection.HTTP_OK) {
                BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                sb = new StringBuilder();
                String response;
                while ((response = br.readLine()) != null){
                    sb.append(response);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

    private String getPostDataString(HashMap<String, String> params) throws UnsupportedEncodingException {
        StringBuilder result = new StringBuilder();
        boolean first = true;
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (first)
                first = false;
            else
                result.append("&");

            result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
            result.append("=");
            result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
        }

        return result.toString();
    }

}



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 : 토스트의 스레드




Related