Android 다 중 스 레 드 처리 의 다 중 스 레 드 상세 설명

handler.post(r)는 사실 스 레 드 가 새로 시작 되 지 않 습 니 다.실행 되 는 runnable 의 run()방법 일 뿐 start()방법 을 실행 하지 않 았 기 때문에 runnable 은 UI 스 레 드 를 걸 었 습 니 다.
1.이렇게 하면 ui 를 조작 할 수 있 지만 run 은 메 인 스 레 드 에 있 습 니 다.인쇄 된 Log 스 레 드 이름 이 main 인 것 을 보면 메 인 스 레 드 임 을 설명 합 니 다.
이것 이 바로 run 방법 에서 ui 를 직접 조작 할 수 있 는 이유 입 니 다.왜냐하면 그것 은 본질 적 으로 ui 스 레 드 이기 때 문 입 니 다.

handler.post(new Runnable(){

  public void run(){

  Log.e("    :",Thread.currrentThread.getName());//    de    main

  setTitle("  ");

   }

});

2.HandlerThread 를 통 해 looper 를 얻 을 수 있 지만 이 run 방법 에서 ui 를 조작 하 는 것 은 불가능 합 니 다.그러나 이것 은 분명 단점 이 있 습 니 다.만약 에 post(r)방법 을 여러 번 실행 하면 사실은 HandlerThread 스 레 드 를 가 는 것 입 니 다.만약 네가 다섯 번,n 번 을 실행한다 면,사실은 한 번 이 고,그것들 은 직렬 이다.만약 5 장의 그림 을 다운로드 한다 면,당신 은 그림 이 첫 번 째 장 을 다 내 려 야만 두 번 째 장 을 내 려 갈 수 있 습 니 다.
주 스 레 드 looper 가 있 는 handler 만 ui 를 조작 할 수 있 고,주 스 레 드 ui 는 handler 의 handlerMessage()방법 에서 Ui 를 조작 할 수 있 으 며,handler 의 post(r)run 방법 에서 Ui 를 조작 할 수 있 음 을 증명 합 니 다.

HandlerThread ht = new HandlerThread("handler thread");

ht.start();

handler = new Handler(ht.getLooper());

handler.post(new Runnable(){//  run()        ht.start()  

  public void run(){

  Log.e("    :",Thread.currrentThread.getName());//       handler thread

  setTitle("  ");//      

  //android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

   }

});

이렇게 하면 어떻게 해 야 합 니까?하하,handler 를 구축 하 는 데 참여 하지 않 아 도 됩 니 다.이 handler 로 메 시 지 를 보 내 고 처리 하 며 위의 handler 로 새 스 레 드 를 엽 니 다.

mainHandler = new Handler(){

  protecket void handlerMessage(Message msg){

    setTitle("  ");//        

  }

}

handler.post(new Runnable(){//  run()        ht.start()  

  public void run(){

  Log.e("    :",Thread.currrentThread.getName());//       handler thread

  mainHandler.sendEmpetMessage();// mainHandler     

  //setTitle("  ");//      

  //android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

   }

});

로그 인쇄:

3.사실 두 번 째 방법 은 번 거 롭 고 비효 율 적 입 니 다.하 나 는 스 레 드 를 시작 하고 하 나 는 메 시 지 를 처리 하 는 데 사 용 됩 니 다.스 레 드 를 시작 하 는 handler 는 looper 가 있어 야 하기 때문에 HanderThread 를 예화 해 야 합 니 다.메 시 지 를 처리 하 는 handler 는 looper 가 필요 하지 않 습 니 다.기본 스 레 드 가 있 는 looper 이기 때문에 이 handler 에서 ui 를 처리 할 수 있 습 니 다.
사실은 하나의 handler 만 예화 하고 메 인 스 레 드 에 인삼 이 없 는 handler 를 구축 한 다음 에 메 시 지 를 보 내 고 처리 할 수 있 습 니 다.스 레 드 를 만 드 는 작업 은 handler 를 사용 하지 않 고 new Thread(r).start()를 사용 합 니 다.그리고 r 의 run()방법 에서 논리 적 인 사 무 를 처리 합 니 다.
이런 모드 로 5 장의 그림 을 다운로드 하면 한 장 한 장 씩 보 여 주 는 그림 을 보지 못 할 수도 있 고,두 번 째 사진 이 먼저 나 올 수도 있 고,동시에 3 장 이 나 올 수도 있 으 며,5 개의 라인 이 무 작위 로 나 올 수도 있다.

private void loadImagesByThread(final String url,final int id){//  Thread new       
     
    new Thread(new Runnable(){ 
 
      @Override 
      public void run() { 
        // TODO Auto-generated method stub 
        Log.e("    :", ""+Thread.currentThread().getName()); 
        Drawable drawable = null; 
        try { 
          drawable = Drawable.createFromStream(new URL(url).openStream(), "image.gif"); 
        } catch (MalformedURLException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
        } catch (IOException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
        } 
        Message msg = mainHandler.obtainMessage(); 
        msg.what = 2012; 
        msg.arg1 = id; 
        msg.obj = drawable; 
        msg.sendToTarget(); 
         
      } 
       
    }).start(); 
  } 
로그 인쇄:

4.AsyncTask
비동기 작업 으로 다 중 작업 모델 을 구성 하 는 것 도 그리 건장 하지 않 으 므 로 여러 개의 AsyncTask 인 스 턴 스 를 만들어 야 합 니 다.하나의 AsyncTask 는 한 번 만 실행 할 수 있 으 며,패스트푸드 류 의 스 레 드 를 한 번 에 다 사용 할 수 없습니다.
AsyncTask 하위 클래스 를 실현 하 는 가장 중요 한 두 가지 방법 중 하 나 는 doInBackground(params)입 니 다.하 나 는 onPost Execute(result)입 니 다.doInBackground()방법 에서 시간 소모 업 무 를 처리 하고 결 과 를 되 돌려 줍 니 다.되 돌아 오 는 값 은 onPost Execute 방법 을 매개 변수 로 한 다음 onPost Execute()에서 결 과 를 ui 에 보 여 줍 니 다.
단계:
① 사례 화 AsyncTask:
AsyncTask 를 실례 화하 고 task.exec(pamas)를 통과 합 니 다.매개 변 수 를 전달 합 니 다.이 매개 변수 목록 은 동적 입 니 다.하나 일 수도 있 고 여러 개 일 수도 있 으 며 길 이 를 가 변 할 수 있 습 니 다.
AsyncTask,첫 번 째 매개 변 수 는 이 방법 으로 doInBackground(params)에 전 달 됩 니 다.두 번 째 매개 변 수 는 데이터 업데이트 값 이 고 세 번 째 는 사 무 를 처리 한 결과 입 니 다.
② onPreExecute 방법:
이 방법 은 인자 도 없고 반환 값 도 없 으 니 이 방법 에서 알림 을 할 수 있 습 니 다.예 를 들 어 show 하나의 Dialog 나 Toast 를 쳐 서 사용자 에 게 다운로드 하기 시작 했다 고 알려 줍 니 다.
③ doInBackground(params)방법:
AsyncTask 내부 구조 에 들 어가 면 먼저 reslut doInBackground(params)방법 을 실행 합 니 다.이 방법 은 시간 이 걸 리 는 사 무 를 처리 합 니 다.exec()의 매개 변 수 는 이 방법 에 매개 변 수 를 전달 하고 반환 값 은 onPostExecute()의 매개 변수 가 됩 니 다.진 도 를 업데이트 하려 면 publicProgress()방법 을 실행 해 야 합 니 다.
④ onProgressUpdate(values)방법:
이 방법의 매개 변 수 는 doInBackground()방법 에서 publicProgress()방법 을 실행 해 야 합 니 다.이 방법 은 매개 변 수 를 onProgressUpdate()방법 에 전달 한 다음 에 이 방법 에서 ui 의 업데이트 전 시 를 할 수 있 습 니 다.예 를 들 어 진도 항목 의 값 은 이 values 값 을 통 해 동태 적 으로 변 할 수 있 습 니 다.
⑤ onPost Execute(result)방법:
여기 가 바로 업무 처리 가 끝 난 방법 입 니 다.doInBackground 방법 이 실 행 된 결 과 는 여기에 전 달 됩 니 다.만약 이 방법 이 데 이 터 를 되 돌려 준다 면.이 방법 에서 Ui 를 처리 할 수 있 고 처 리 된 데 이 터 를 ui 에 보 여줄 수 있 습 니 다.예 를 들 어 그림,문자,네가 원 하 는 모든 결과.

private void loadImageByAsyncTask(final String url,final int id){//      ,     handler       
    DownloadTask task = new DownloadTask(); 
    task.execute(""+id,url);//AsyncTask       
  } 
   
  class DownloadTask extends AsyncTask<String,Integer,Drawable>{ 
 
    int id; 
    @Override 
    protected Drawable doInBackground(String... params) {//params  url   id     
      // TODO Auto-generated method stub 
      Log.e("    :", ""+Thread.currentThread().getName()); 
      Drawable drawable = null; 
      this.id = Integer.parseInt(params[0]); 
      try { 
        drawable = Drawable.createFromStream(new URL(params[1]).openStream(), "image.gif"); 
      } catch (MalformedURLException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
      } catch (IOException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
      } 
       
      return drawable; 
    } 
 
    @Override 
    protected void onPostExecute(Drawable result) { 
      // TODO Auto-generated method stub 
      super.onPostExecute(result); 
      ((ImageView)MainActivity.this.findViewById(id)).setImageDrawable(result); 
    } 
 
    @Override 
    protected void onPreExecute() { 
      // TODO Auto-generated method stub 
      super.onPreExecute(); 
    } 
 
    @Override 
    protected void onProgressUpdate(Integer... values) { 
      // TODO Auto-generated method stub 
      super.onProgressUpdate(values); 
    } 
 
     
  } 
여기 인쇄 된 log
 
5.ExecutorServie 스 레 드 탱크
Executors 의 정적 방법 으로 만 듭 니 다.보통 세 가지 가 있 습 니 다.
1.단일 스 레 드:Executors.newSingleThreadExecutor();
2.고정 수량 스 레 드:Executors.newFixedThreadPool();
3.동적 스 레 드:Executors.newCachedThreadPool();
여기 서 저 희 는 고정 5 개의 스 레 드 로 응용 합 니 다.사용 방법 은 ExecutorService 대상 을 만 든 다음 submit(r)를 실행 하면 Runnable 대상 을 시작 할 수 있 습 니 다.스 레 드 탱크 로 관리 하 는 장점 은 시스템 의 안정 적 인 운행 을 확보 하고 대량의 스 레 드,높 은 작업량 의 상황 에서 사용 할 수 있다 는 것 이다.만약 에 1000 장의 그림 을 보 여 주 려 면 1000 개의 스 레 드 를 만들어 서 불 러 오 면 시스템 이 죽 을 것 이다.스 레 드 탱크 를 사용 하면 이 문 제 를 피 할 수 있 습 니 다.5 개의 스 레 드 로 돌아 가면 서 실행 할 수 있 습 니 다.5 개의 한 조 가 실 행 된 스 레 드 는 직접 회수 하지 않 고 다음 에 실 행 될 때 까지 기다 릴 수 있 습 니 다.그러면 시스템 에 대한 비용 을 많이 줄 일 수 있 습 니 다.

private void loadImagesByExecutors(final String url,final int id){ 
    service.submit(new Runnable(){ 
       
      @Override 
      public void run() { 
        // TODO Auto-generated method stub 
        Log.e("    :", ""+Thread.currentThread().getName()); 
         
        try { 
          final Drawable drawable = Drawable.createFromStream(new URL(url).openStream(), "image.gif"); 
          mainHandler.post(new Runnable(){ 
 
            @Override 
            public void run() {//         
              // TODO Auto-generated method stub 
              ((ImageView)MainActivity.this.findViewById(id)).setImageDrawable(drawable); 
            } 
          }); 
           
        } catch (MalformedURLException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
        } catch (IOException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
        } 
         
      } 
       
    }); 
     
  } 
Log:
 
사실 분명히 말 하지 못 했 을 수도 있 습 니 다.첫 번 째 는 다 중 스 레 드 가 아 닙 니 다.
1.loadImages ByHandler()는 Handler.post()방법 을 통 해 두 개의 Handler 를 구축 하여 통신 한다.
2.loadImages ByThread(),이것 은 직접 new Thread()에서 스 레 드 를 시작 합 니 다.메 인 스 레 드 의 handler 에서 메 시 지 를 처리 합 니 다.
3.loadImage ByAsyncTask(),이 작업 은 비동기 작업 을 사용 합 니 다.모든 것 이 내부 구조 에서 이 루어 지고 안에서 Ui 를 조작 할 수 있 습 니 다.
4.loadImages ByExecutors()는 스 레 드 탱크 를 사용 하여 스 레 드 를 제어 할 수 있 고 안정 적 인 운행 을 보장 합 니 다.
사실 자주 사용 하 는 것 은 바로 뒤의 세 가지 이다.두 번 째 용법 은 유연 하고 간단 하지만 대량의 임무 에 적합 하지 않다.세 번 째 는 일반적으로 하나의 임무,일회 성 임무 에 적용 된다.네 번 째 는 보통 대량의 고밀도 로 실 행 된 사용 상황,예 를 들 어 그림 을 대량으로 불 러 오고 파일 을 대량으로 다운로드 하 는 등 이다.
그림 을 보 세 요.

모든 원본 코드:

package com.bvin.exec; 
 
import java.io.IOException; 
import java.net.MalformedURLException; 
import java.net.URL; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
 
import android.app.Activity; 
import android.graphics.drawable.Drawable; 
import android.os.AsyncTask; 
import android.os.Bundle; 
import android.os.Handler; 
import android.os.HandlerThread; 
import android.os.Message; 
import android.util.Log; 
import android.view.View; 
import android.widget.Button; 
import android.widget.ImageView; 
 
public class MainActivity extends Activity { 
  /** Called when the activity is first created. */ 
   
  private Handler handler ; 
  private Button bt; 
  private Handler mainHandler = new Handler(){ 
 
    @Override 
    public void handleMessage(Message msg) { 
      // TODO Auto-generated method stub 
      super.handleMessage(msg); 
      if(msg.what == 2012){ 
        //           ui  
        ((ImageView)MainActivity.this.findViewById(msg.arg1)).setImageDrawable((Drawable)msg.obj); 
      } 
    } 
     
     
  }; 
   
  private ExecutorService service = Executors.newFixedThreadPool(5); 
   
  @Override 
  public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
    initViews(); 
    HandlerThread ht = new HandlerThread("down image thread"); 
    ht.start(); 
    handler = new Handler(ht.getLooper()){//    looper    handler      ui  
 
      @Override 
      public void handleMessage(Message msg) { 
        // TODO Auto-generated method stub 
        super.handleMessage(msg); 
         
         
      } 
       
    }; 
     
  } 
   
  private void initViews(){ 
     
    bt = (Button)findViewById(R.id.bt); 
    bt.setOnClickListener(new View.OnClickListener() { 
       
      @Override 
      public void onClick(View v) { 
        // TODO Auto-generated method stub 
        loadImagesByExecutors("http://news.baidu.com/z/resource/r/image/2012-11-23/23c1625aca99f02c50d8e510383a34e7.jpg",R.id.iv1); 
        loadImagesByExecutors("http://news.baidu.com/z/resource/r/image/2012-11-23/c4698d97ef6d10722c8e917733c7beb3.jpg",R.id.iv2); 
        loadImagesByExecutors("http://news.baidu.com/z/resource/r/image/2012-11-23/f332ffe433be2a3112be15f78bff5a40.jpg",R.id.iv3); 
        loadImagesByExecutors("http://news.baidu.com/z/resource/r/image/2012-11-23/6ff8a9c647a1e80bc602eeda48865d4c.jpg",R.id.iv4); 
        loadImagesByExecutors("http://news.baidu.com/z/resource/r/image/2012-11-23/f104d069f7443dca52a878d779392874.jpg",R.id.iv5); 
      } 
    }); 
  } 
   
  private void loadImagesByHandler(final String url,final int id){//    looper handler.post(runnable),     
     
     
    handler.post(new Runnable(){//  handler  Looper             
 
      @Override 
      public void run() { 
        // TODO Auto-generated method stub 
        Log.e("    :", ""+Thread.currentThread().getName()); 
        Drawable drawable = null; 
        try { 
          drawable = Drawable.createFromStream(new URL(url).openStream(), "image.gif"); 
        } catch (MalformedURLException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
        } catch (IOException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
        } 
        //SystemClock.sleep(2000); 
        //((ImageView)MainActivity.this.findViewById(id)).setImageDrawable(drawable); 
        Message msg = mainHandler.obtainMessage(); 
        msg.what = 2012; 
        msg.arg1 = id; 
        msg.obj = drawable; 
        msg.sendToTarget(); 
      } 
       
    }); 
     
     
  } 
   
  private void loadImagesByThread(final String url,final int id){//  Thread new       
     
    new Thread(new Runnable(){ 
 
      @Override 
      public void run() { 
        // TODO Auto-generated method stub 
        Log.e("    :", ""+Thread.currentThread().getName()); 
        Drawable drawable = null; 
        try { 
          drawable = Drawable.createFromStream(new URL(url).openStream(), "image.gif"); 
        } catch (MalformedURLException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
        } catch (IOException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
        } 
        Message msg = mainHandler.obtainMessage(); 
        msg.what = 2012; 
        msg.arg1 = id; 
        msg.obj = drawable; 
        msg.sendToTarget(); 
         
      } 
       
    }).start(); 
  }  
 
  private void loadImageByAsyncTask(final String url,final int id){//      ,     handler       
    DownloadTask task = new DownloadTask(); 
    task.execute(""+id,url);//AsyncTask       
  } 
   
  private void loadImagesByExecutors(final String url,final int id){ 
    service.submit(new Runnable(){ 
       
      @Override 
      public void run() { 
        // TODO Auto-generated method stub 
        Log.e("    :", ""+Thread.currentThread().getName()); 
         
        try { 
          final Drawable drawable = Drawable.createFromStream(new URL(url).openStream(), "image.gif"); 
          mainHandler.post(new Runnable(){ 
 
            @Override 
            public void run() {//         
              // TODO Auto-generated method stub 
              ((ImageView)MainActivity.this.findViewById(id)).setImageDrawable(drawable); 
            } 
          }); 
           
        } catch (MalformedURLException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
        } catch (IOException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
        } 
         
      } 
       
    }); 
     
  } 
   
  class DownloadTask extends AsyncTask<String,Integer,Drawable>{ 
 
    int id; 
    @Override 
    protected Drawable doInBackground(String... params) {//params  url   id     
      // TODO Auto-generated method stub 
      Log.e("    :", ""+Thread.currentThread().getName()); 
      Drawable drawable = null; 
      this.id = Integer.parseInt(params[0]); 
      try { 
        drawable = Drawable.createFromStream(new URL(params[1]).openStream(), "image.gif"); 
      } catch (MalformedURLException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
      } catch (IOException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
      } 
       
      return drawable; 
    } 
 
    @Override 
    protected void onPostExecute(Drawable result) { 
      // TODO Auto-generated method stub 
      super.onPostExecute(result); 
      ((ImageView)MainActivity.this.findViewById(id)).setImageDrawable(result); 
    } 
 
    @Override 
    protected void onPreExecute() { 
      // TODO Auto-generated method stub 
      super.onPreExecute(); 
    } 
 
    @Override 
    protected void onProgressUpdate(Integer... values) { 
      // TODO Auto-generated method stub 
      super.onProgressUpdate(values); 
    } 
 
     
  } 
} 



이상 은 안 드 로 이 드 다 중 스 레 드 에 대한 자료 정리 입 니 다.추 후 관련 지식 을 계속 보충 하 겠 습 니 다.본 사이트 에 대한 지원 에 감 사 드 립 니 다!

좋은 웹페이지 즐겨찾기