Android Handler 와 스 레 드 간 통신 ITC 에 대한 상세 한 설명

'Android Handler 메시지 순환 에 대한 심도 있 는 분석'에서 Handler 는 스 레 드 내부 의 메시지 대기 열 을 조작 하 는 데 사용 되 기 때문에 Handler 는 스 레 드 간 통신 ITC 에 사용 할 수 있 는데 이런 방식 은 더욱 안전 하고 효율 적 이 며 동기 화 된 고민 을 크게 줄 일 수 있 고 심지어 synchronized 를 사용 하지 않 아 도 된다.스 레 드 간 통신 ITC 의 정상 적 인 상황 에서 함수 호출 스 택 은 같은 스 레 드 에서 생존 합 니 다.실행 논 리 를 다른 스 레 드 로 교환 하려 면 Thread 를 새로 만 든 다음 start()를 만 들 수 있 습 니 다.또 다른 방법 은 ITC,즉 메시지 대기 열 로 이 루어 지 는 것 입 니 다.스 레 드 는 실행 논 리 를 다른 스 레 드 에 전달 해 야 할 때 다른 스 레 드 의 메시지 대기 열 에 메 시 지 를 보 냅 니 다.메 시 지 를 보 낸 후 함수 가 끝나 고 스 택 호출 도 중단 합 니 다.메시지 큐 에 메시지 가 있 을 때 스 레 드 는 처리 메 시 지 를 깨 워 서 실행 논 리 를 한 스 레 드 에서 다른 스 레 드 로 옮 깁 니 다.이 는 스 레 드 간 통신 ITC 를 실현 하고 진행 간 통신 IPC 와 유사 한 사상 을 가진다.주 스 레 드 에 Handler 를 만 든 다음 새 스 레 드 에서 이 Handler 를 사용 하여 주 스 레 드 와 통신 하 는 것 이 일반적인 방법 입 니 다.메 인 스 레 드 의 메시지 큐 가 만 들 어 졌 기 때문에 Handler 를 직접 만 들 면 됩 니 다.새 스 레 드 는 직접 사용 할 수 있 습 니 다.다 중 스 레 드 간 통신 이 필요 한 경우 에는 모든 스 레 드 에 Message Queue 와 Handler 를 만들어 야 합 니 다.스 레 드 가 다른 스 레 드 에 접근 할 수 있 는 Handler 만 있 으 면 통신 할 수 있 습 니 다.Handler 를 올 바 르 게 만 들 려 면 Handler 가 스 레 드 와 연결 되 어야 하기 때문에 Handler 를 초기 화 할 때 주의해 야 합 니 다.Handler 에 Looper 대상 new Handler(Looper)를 지정 하면 이 Handler 는 Looper 대상 이 있 는 스 레 드 에 연결 되 고 Handler 의 메시지 처리 리 셋 은 그 스 레 드 에서 실 행 됩 니 다.스 레 드 를 만 들 때 Looper 대상 을 지정 하지 않 으 면 이 Handler 는 이 Handler 를 만 드 는 스 레 드 에 연결 되 어 메시지 리 셋 처리 가 그 스 레 드 에서 실 행 됩 니 다.따라서 다음 과 같이 쓰 십시오.

private class CookServer extends Thread {
       private Handler mHandler = new Handler() {
               public void handleMessage(Message msg) {
                     ....
                }
        };
이렇게 쓰 면 이 mHandler 는 이 CookerServer 를 만 드 는 스 레 드 와 연결 되 고 handleMessage 도 실 행 됩 니 다.분명히 메 인 스 레 드 가 new CookServer()를 호출 하면 mHandler 는 메 인 스 레 드 에서 실 행 됩 니 다.올 바른 쓰기 방법 은 다음 과 같 습 니 다.

private class CookServer extends Thread {
       public void run() {
             Looper.prepare();
                 // or new Handler(Looper.myLooper())
                 private Handler mHandler = new Handler() {
                       public void handleMessage(Message msg) {
                     ....
                }
        };
Handler Thread 는 한 스 레 드 에서 메시지 큐 와 Handler 를 사용 하려 면 Android API 에 포 장 된 Handler Thread 클래스 가 있 습 니 다.이 클래스 는 Looper 초기 화 작업 을 마 쳤 습 니 다.당신 이 해 야 할 일 은 onLooper Prepared()방법 을 다시 쓰 는 것 입 니 다.그 중에서 Handler:

private class DeliverServer extends HandlerThread {
      private Handler mHandler;
      public DeliverServer(String name) {
           super(name);
      }
      @Override
      public void onLooperPrepared() {
            mHandler = new Handler(getLooper()) {
                    public void handleMessage(Message msg) {
                        .....
                    }
             };
       }
}
인 스 턴 스 를 만 들 었 습 니 다.이 인 스 턴 스 는 인터넷 주문 시스템 을 모 의 했 습 니 다.고객 은'Submit order'를 클릭 하여 주문 서 를 만 들 었 습 니 다.메 인 스 레 드 에서 주문 서 를 수집 한 다음 에 CookServer 에 맡 겼 습 니 다.CookServer 는 제작 이 끝 난 후에 DeliverServer 에 맡 겨 서 음식 을 고객 에 게 운송 할 것 입 니 다.이로써 주문 서 를 완성 합 니 다.동시에 CookServer 와 DeliverServer 는 상 태 를 업데이트 합 니 다.

/**
 * How to attach an Handler to a Thread:
 * If you specify Looper object to Handler, i.e. new Handler(Looper), then the handler is attached to the thread owning
 * the Looper object, in which handleMessage() is executed.
 * If you do not specify the Looper object, then the handler is attached to the thread calling new Handler(), in which
 * handleMessage() is executed.
 * In this example, for class CookServer or DeliverServer, if you write this way:
 *     private class CookServer extends Thread {
  private Handler mHandler;
  private Looper mLooper;

  public CookServer() {
   mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
     ....
    }
       start();
  }
 * then mHandler is attached to thread calling new CookServer(), which is the main thread, so mHandler.handleMessage() will
 * be executed in main thread.
 * To attach mHandler to its own thread, you must put it in run(), or after mLooper is created. For our example, providing
 * mLooper or not won't matter, because new Handler() is called in run(), which is in a new thread.
 */
public class HandlerITCDemo extends ListActivity {
    private static final int COOKING_STARTED = 1;
    private static final int COOKING_DONE = 2;
    private static final int DELIVERING_STARTED = 3;
    private static final int ORDER_DONE = 4;

    private ListView mListView;
    private static final String[] mFoods = new String[] {
 "Cubake",
 "Donut",
 "Eclaire",
 "Gingerbread",
 "Honeycomb",
 "Ice Cream Sanwitch",
 "Jelly Bean",
    };
    private ArrayList<String> mOrderList;
    private TextView mGeneralStatus;
    private Button mSubmitOrder;
    private static Random mRandomer = new Random(47);
    private int mOrderCount;
    private int mCookingCount;
    private int mDeliveringCount;
    private int mDoneCount;

    private Handler mMainHandler = new Handler() {
 @Override
 public void handleMessage(Message msg) {
     switch (msg.what) {
     case COOKING_STARTED:
  mCookingCount++;
  break;
     case COOKING_DONE:
  mCookingCount--;
  break;
     case DELIVERING_STARTED:
  mDeliveringCount++;
  break;
     case ORDER_DONE:
  mDeliveringCount--;
  mDoneCount++;
     default:
  break;
     }
     mGeneralStatus.setText(makeStatusLabel());
 }
    };

    private CookServer mCookServer;
    private DeliverServer mDeliverServer;

    @Override
    protected void onDestroy() {
 super.onDestroy();
 if (mCookServer != null) {
     mCookServer.exit();
     mCookServer = null;
 }
 if (mDeliverServer != null) {
     mDeliverServer.exit();
     mDeliverServer = null;
 }
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 mListView = getListView();
 mOrderList = new ArrayList<String>();
 mGeneralStatus = new TextView(getApplication());
 mGeneralStatus.setText(makeStatusLabel());
 mSubmitOrder = new Button(getApplication());
 mSubmitOrder.setText("Submit order");
 mSubmitOrder.setOnClickListener(new View.OnClickListener() {
     public void onClick(View v) {
  String order = mFoods[mRandomer.nextInt(mFoods.length)];
  mOrderList.add(order);
  mOrderCount = mOrderList.size();
  mGeneralStatus.setText(makeStatusLabel());
  setAdapter();
  mCookServer.cook(order);
     }
 });
 mListView.addHeaderView(mGeneralStatus);
 mListView.addFooterView(mSubmitOrder);
 setAdapter();
 mCookServer = new CookServer();
 mDeliverServer = new DeliverServer("deliver server");
    }

    private String makeStatusLabel() {
 StringBuilder sb = new StringBuilder();
 sb.append("Total: ");
 sb.append(mOrderCount);
 sb.append("    Cooking: ");
 sb.append(mCookingCount);
 sb.append("    Delivering: ");
 sb.append(mDeliveringCount);
 sb.append("    Done: ");
 sb.append(mDoneCount);
 return sb.toString();
    }

    private void setAdapter() {
 final ListAdapter adapter = new ArrayAdapter<String>(getApplication(), android.R.layout.simple_list_item_1, mOrderList);
 setListAdapter(adapter);
    }

    private class CookServer extends Thread {
 private Handler mHandler;
 private Looper mLooper;

 public CookServer() {
     start();
 }

 @Override
 public void run() {
     Looper.prepare();
     mLooper = Looper.myLooper();
     mHandler = new Handler(mLooper, new Handler.Callback() {
  public boolean handleMessage(Message msg) {
      new Cooker((String) msg.obj);
      return true;
  }
     });
     Looper.loop();
 }

 public void cook(String order) {
     if (mLooper == null || mHandler == null) {
  return;
     }
     Message msg = Message.obtain();
     msg.obj = order;
     mHandler.sendMessage(msg);
 }

 public void exit() {
     if (mLooper != null) {
  mLooper.quit();
  mHandler = null;
  mLooper = null;
     }
 }
    }

    private class Cooker extends Thread {
 private String order;
 public Cooker(String order) {
     this.order = order;
     start();
 }

 @Override
 public void run() {
            mMainHandler.sendEmptyMessage(COOKING_STARTED);
            SystemClock.sleep(mRandomer.nextInt(50000));
            mDeliverServer.deliver(order);
            mMainHandler.sendEmptyMessage(COOKING_DONE);
 }
    }

    private class DeliverServer extends HandlerThread {
 private Handler mHandler;

 public DeliverServer(String name) {
     super(name);
     start();
 }

 @Override
 protected void onLooperPrepared() {
     super.onLooperPrepared();
     mHandler = new Handler(getLooper(), new Handler.Callback() {
  public boolean handleMessage(Message msg) {
      new Deliver((String) msg.obj);
      return true;
  }
     });
 }
 public void deliver(String order) {
     if (mHandler == null || getLooper() == null) {
  return;
     }
     Message msg = Message.obtain();
     msg.obj = order;
     mHandler.sendMessage(msg);
 }

 public void exit() {
     quit();
     mHandler = null;
 }
    }

    private class Deliver extends Thread {
 private String order;
 public Deliver(String order) {
     this.order = order;
     start();
 }

 @Override
 public void run() {
     mMainHandler.sendEmptyMessage(DELIVERING_STARTED);
     SystemClock.sleep(mRandomer.nextInt(50000));
     mMainHandler.sendEmptyMessage(ORDER_DONE);
 }
    }
}

좋은 웹페이지 즐겨찾기