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

BLE scan 스레드에서 전역 데이터를 접근 및 수정할 경우에 대한 질문

0 추천

안녕하세요. 안드로이드를 경험하고 있는 미숙한 개발자입니다.

안드로이드도 미흡하지만 자바에 대해서도(특히 스레드 부분에 대해) 애매하게 알고 있는 부분이 많아 이렇게 질문을 드리게 되었습니다.

 

질문 사항

onLeScan() 메소드가 멀티스레드로 많이 호출되는 상황이라, 그 안에서 다른 스레드와 영향이 있는(수정되는) 정보를 접근하는 것이 조심스럽습니다. 조심스럽게 접근하려고 사용한 방식들을 아래에 적었는데, 필요없거나 잘못사용하고 있는 부분이 있으면 조언 부탁 드립니다.

1. ConcurrentHashMap

다수의 블루투스 및 한 블루투스에서도 해당 쓰레드가 여러번 도는 상황이라 HashMap을 안쓰고 이걸 썼는데요. 이게 효과가 있까요?

2. synchronized 영역

BtInstance 에서 rssiList를 접근 및 추가할때 동기화 블록을 사용하였는데요. 바람직한가요?

3. btRssTextView.setText() 시점

여러개의 블루투스의 마지막 수신된 rssi 값을 각각 보여주어야 하는데요.

하나라도 새로운 값이 들어올 경우 텍스트를 갱신하기 위하여 onLeScan() 안에서 작업하고 있습니다.

너무 비효율적인 것 같은데, 다른 시점에서 작업할 수 있을까요?

 

코드목적: 블루투스 스캔을 통해 현재 인식되는 모든 블루투스에 대한 rssi 값을 저장(누적)하여 받은 값들을 파일로 떨구기.

1. 스캔 시작

2. 블루투스 rssi를 받을 때마다 onLeScan()이 호출됨. 주변 블루투스에서 1초에 2~3번 신호를 보내줌

3. onLeScan() 안에서 인자로 받은 현재 rssi 값을 해당 블루투스 객체의 rssi 리스트에 추가함. 스캔이 끝날때까지 누적시킨다.

(스캔이 될 때마다 각 블루투스 객체의 List<Integer> 에 rssi 값을 add 시키기)

4. 텍스트뷰에 스캔되는 블루투스 정보와 각각 마지막에 수집된 rssi 값을 나타내기

5. 스캔 종료

6. 수집된 블루투스들 각각의 rssi 누적 값을 파일로 떨구기

7. 파일 예시

 BT A

   mac: xx:aa~~~

   rssi: -59, -61, -67, -71, -70

 BT B

   mac: xx:aa~~~

   rssi: -71, -70, -74, -78, -76

 ...

 

코드는 아래와 같습니다.

// 수집된 블루투스를 담는 맵.
ConcurrentHashMap<String,BtInstance> btMap = new ConcurrentHashMap<String,BtInstance>();

method() {
	...
	btAdapter.startLeScan(new LeScanCallback() {
		
		@Override
		public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {

			String mac = device.getAddress();
			BtInstance btInstance = null;
			if(btMap.containsKey(mac)) {
				btInstance = btMap.get(mac);
			} else {
				btInstance = new BtInstance(mac);
			}
			
			btInstance.addRssiList(rssi);
			
			// 수집된 블루투스들의 마지막 수신된 rssi 값을 텍스트로 보여준다.
			StringBuffer sBuffer = new StringBuffer();
			for (BtInstance bt : btMap.values()) {
				List<Integer> rssList  = bt.getRssiList();
				sBuffer.append("mac: ");
				sBuffer.append(bt.getMac());
				sBuffer.append("last rssi: ");
				sBuffer.append(rssList.get(rssList.size()+1));
				sBuffer.append("\n");
			}
			btRssTextView.setText(sBuffer.toString());
		}
	});
	...
}

/**
 * 블루투스 객체. mac과 수신받은 rssi 리스트를 갖는다.
 */
class BtInstance {
	private String mac;
	private List<Integer> rssiList = new ArrayList<Integer>();
	
	public BtInstance(String mac) {
		this.mac = mac;
	}

	public String getMac() {
		return mac;
	}
	
	public List<Integer> getRssiList() {
		synchronized (rssiList) {
			return rssiList;	
		}
	}

	public void addRssiList(int rssi) {
		synchronized (rssiList) {
			rssiList.add(rssi);	
		}
	}		
}

 

좋은 가이드 부탁 드립니다.

따귀 (120 포인트) 님이 2016년 3월 23일 질문
따귀님이 2016년 3월 24일 수정

답변 달기

· 글에 소스 코드 보기 좋게 넣는 법
· 질문에 대해 추가적인 질문이나 의견이 있으면 답변이 아니라 댓글로 달아주시기 바랍니다.
표시할 이름 (옵션):
개인정보: 당신의 이메일은 이 알림을 보내는데만 사용됩니다.
스팸 차단 검사:
스팸 검사를 다시 받지 않으려면 로그인하거나 혹은 가입 하세요.
...