"이젠 비동기 없인 살 수 없는 몸이 되어버렸어"
동기와 비동기의 차이점을 쉽게 설명하자면..
이번에 동기화 이슈가 발생한 기능은 간단하게 여러 대의 기기에 압축한 zip파일을 전송하는 기능인데, 통신 방식으로 Retrofit을 사용하다 보니 한 번에 여러 대의 기기로 전송 시 각 기기마다 같은 파일인데도 불구하고 여러 번 압축하는 문제가 발생하였고, 기능 자체에는 문제가 없지만 성능면에서 떨어질 수 있기 때문에 이 방식을 파일 압축시 처음 한 번만 압축 후 생성된 zip파일을 나머지 기기에 전송하는 식으로 변경하였습니다.
굉장히 간단한 문제지만 동기화와 비동기에 대해 지식이 부족하다면 처리하기 힘든 문제일 수도 있다고 생각했습니다.
문제가 발생한 코드입니다.
@Subscribe
public void onVerifyDoneEvent(VerifySuccessEvent oEvent){
if (oEvent.isSuccess()){
ArrayList<String> aOItem = oEvent.getFileList();
if(aOItem != null && aOItem.size() > 0){
ZipFromFileListTask oTask = new ZipFromFileListTask(aOItem,new ICreateZipCallback() {
@Override
public void onICreateZipCallback(boolean result, String sFilePath, String sMd5, String sMes) {
if(result){
EventBus.getDefault().post(new ZipSuccessEvent(true, sFilePath, sMd5, oEvent.getDevice(), oEvent.getExecItem()));
}
}
});
}else{
EventBus.getDefault().post(new UploadSuccessEvent(true, oEvent.getDevice(), oEvent.getExecItem()));
}
}
}
기존 코드는 이런식으로 Eventbus를 통해 들어온 이벤트가 성공했으면 이벤트의 파일리스트를 확인하고 파일리스트가 비어있지 않다면 미리 만들어놓은 ZipFromFileListTask를 사용하여 zip파일을 만들고 만든 파일의 경로를 또다른 이벤트로 넘기는 함수입니다.
이때 예를들어 파일을 5대에 기기에 전송하면 5개의 스레드들이 이 함수로 들어오기 때문에 각 스레드들은 똑같은 파일을 한번씩 압축하여 총 5번 압축하여 전송하는 번거로움이 있습니다.
이제 수정한 코드를 살펴보면
@Subscribe
public synchronized void onVerifyDoneEvent(VerifySuccessEvent oEvent){
if (oEvent.isSuccess()){
ArrayList<String> aOItem = oEvent.getFileList();
if(aOItem != null && aOItem.size() > 0){
File file = new File(filePath);
String md5 = CoreUtils.calMD5(file);
if (file.exists()){
EventBus.getDefault().post(new ZipSuccessEvent(true, filePath, md5, oEvent.getDevice(), oEvent.getExecItem()));
}
ZipFromFileListTask oTask = new ZipFromFileListTask(aOItem,new ICreateZipCallback() {
@Override
public void onICreateZipCallback(boolean result, String sFilePath, String sMd5, String sMes) {
if(result){
filePath = sFilePath;
EventBus.getDefault().post(new ZipSuccessEvent(true, sFilePath, sMd5, oEvent.getDevice(), oEvent.getExecItem()));
}
}
}
});
}else{
EventBus.getDefault().post(new UploadSuccessEvent(true, oEvent.getDevice(), oEvent.getExecItem()));
}
}
}
synchronized
키워드를 이용해 한번에 하나의 스레드만이 이 함수를 사용할 수 있게 합니다.
처음 들어온 스레드에서 파일의 존재 여부를 확인하고 파일이 존재하지 않는다면 위의 기존 코드와 같이 새로 파일을 생성한 후 생성한 파일의 경로를 filePath
변수에 저장합니다.
함수가 끝난후 다음부터 들어오는 스레드들은 미리 만들어진 경로의 파일 유무를 확인하여 그 파일로 이벤트를 보내게 됩니다.