마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

Thread 순서제어 문제

0 추천

먼저 문제점이, 웹페이지 에서 받은 JSON 데이터를 가지고 proximityAlert를 달고 또, 맵뷰에 표시를 해야됩니다.

그래서 순서제어가되는 aysncTask를 썼는데요.

 doInBackGround에서 데이터를 받고 onPostExecute()에서 proximityAlert를 달았습니다.

테스트 해보니까 async.execute()가 실행되는 시점에만 리스너가 작동하고 이후에는 작동이 안합니다.

아마 async가 죽으면서 안에있는 리스너들도 다 죽는거 습니다.

AsyncTask에 이 문제를 해결해주는 기능이 없으면, Thread를 써야 될거 같은데

Thread를 쓰면 순서제어를 어떻게 해야될지 모르겠습니다. 받은 데이터가지고 뷰에 쏴주기도 해야되는데 머리가 복잡하네요

아래는 순서제어 해볼려고 제가 짜본것이고 onResume에서 threadAlert.start()

onMapReady에서 threadMarker.start(), threadGetList.start() 하고있습니다. 가끔씩 Log르 보니 가끔씩 순서가 뒤섞이긴 하는데 제대로 작동해도 맵에 리스너와 마커가 달리지 않네요,,,

threadAlert.setPriority(2);
threadMarker.setPriority(2);
threadGetList.setPriority(1);
    class MethodeHolder {

        boolean alertState = false;
        boolean markerState = false;

        public synchronized void getJSON(){
            Log.i("MapsActivity>>","getJSONStart");
            while(alertState !=true && markerState !=true){
                Log.i("MapsActivity>>","getJSONwait");
            }
            alertState = false;
            markerState = false;
            try {
                listVO = reqDAO.getAccidentJson(); //네트워크에서 json을 가져와 리스트에  담음
            } catch (JSONException e) {
                e.printStackTrace();
            }
            notifyAll();
        }//end getJSON

        public synchronized void addMarker(){
            Log.i("MapsActivity>>","addMarkerWait");
            try {
                markerState = true;
                wait();
                Log.i("MapsActivity>>","addMarkerStart");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    Iterator<AccidentVO> iterator = listVO.iterator();

                    for(int i=0; i<makerList.size();i++){
                        if(makerList.get(i) != null){
                            makerList.get(i).remove();  //마커지우기
                        }
                    }
                    makerList.clear();

                    //새로등록
                    while(iterator.hasNext()) {
                        AccidentVO tempVO = iterator.next();
                        iterator.remove();
                        if(tempVO.getStatus().equals("occured")){
                            LatLng position = new LatLng(tempVO.getLatitude(), tempVO.getLongitude());
                            makerList.add(mMap.addMarker(new MarkerOptions().position(position).title("Here").icon(BitmapDescriptorFactory.fromResource(R.drawable.warning2)))); 
                            makerList.get(tempVO.getNum()).showInfoWindow();
                        }
                    }//end while
                }
            });
        }//end addMarker()

        public synchronized void addAlert(){
            Log.i("MapsActivity>>","addAlertWait");
            try {
                alertState = true;
                wait();
                Log.i("MapsActivity>>","addAlertStart");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Iterator<AccidentVO> iterator = listVO.iterator();

            if (ActivityCompat.checkSelfPermission(MapsActivity.this, Manifest.permission.ACCESS_FINE_LOCATION)
                    != PackageManager.PERMISSION_GRANTED &&
                    ActivityCompat.checkSelfPermission(MapsActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION)
                            != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(MapsActivity.this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},REQUEST_FINE_ACCESS);
                ActivityCompat.requestPermissions(MapsActivity.this,new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},REQUEST_COARSE_LOCATION);
            } //권한추가

            //이전 정보들 지우기
            if(mLocMgr !=null) {
                mLocMgr.removeProximityAlert(mPending100); //접근 알람 지우기
            }

            //새로등록
            while(iterator.hasNext()) {
                AccidentVO tempVO = iterator.next();
                iterator.remove();

                if(tempVO.getStatus().equals("occured")){
                    mLocMgr.addProximityAlert(tempVO.getLatitude(), tempVO.getLongitude(), (float)sensingRadius100,-1,mPending100);    //접근알람 등록
                }
            }//end while
        }//end addAlert();
    }//end class

    Thread threadGetList = new Thread(new Runnable() {
        @Override
        public void run() {
            methodeHolder.getJSON();
        }
    });


    Thread threadMarker = new Thread(new Runnable() {
        @Override
        public void run() {
            methodeHolder.addMarker();
        }
    });


    Thread threadAlert = new Thread(new Runnable() {
        @Override
        public void run() {
            methodeHolder.addAlert();
        }
    });
android:name (450 포인트) 님이 2017년 6월 14일 질문
android:name님이 2017년 6월 14일 수정
순서가 걱정이시면 싱크를 걸어도 되구요 그게 좀 어려우시면
쓰레드 > 핸들러 > 핸들러에서 기능수행후 다음쓰레드호출 식으로 짜서 돌려보세요

1개의 답변

0 추천
님이 원하시는 기능이 Structured Concurrency인데 (예를 들어, 두개의 쓰레드를 동시에 실행 한 후, 두개가 다 끝날 때까지 기다렸다 처리하는 것), 이걸 해결하려면 RxJava 같은 라이브리러를 사용하거나 (코틀린이라면 코루틴 -  eg. coroutine join) Thread 제어하는 코드를 작성하셔야 하는데,  그 기능을 위해서 RxJava를 사용하는 것은 오버킬 같구요. 아래 라이브러리가 용량도 작고 원하시는 기능을 잘 수행해줄 것 같습니다.

https://github.com/techyourchance/thread-poster

사용법도 간단하고 소스코드를 보시면 어떻게 쓰레드를 제어하는지 알 수도 있을 겁니다.
spark (227,830 포인트) 님이 2021년 4월 24일 답변
spark님이 2021년 4월 24일 수정
...