최근 coroutine , rx 로 인해 쓰레드 체 관한 처리가 조금 쉬워지긴했다.
그래도 옛날 소스들을 보면 java thread, Executor 또는 AsyncTask를 이용해서 만들어진게 많다.
이중 주로 외부랑 httpd 통신할때 쓰면 Executor 에 대해 알아보자.
그전에 어차피 나올용어로서 Callable 과 Runnable을 알아보자
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | static class MyCallable implements Callable<String> { @Override public String call() throws Exception { return "hehe"; } } /* 사용 ExecutorService mPool = Executors.newFixedThreadPool(5); mPool.execute(new MyRunnable()); */ static class MyRunnable implements Runnable { @Override public void run(){ } } /* 사용 Future<String> mFuture = mPool.submit(new MyCallable()); try { // 미래(future)에서 데이터가 오기까지 여기는 런타임 블럭처리된다. Log.e("from Future", mFuture.get()); } catch (ExecutionException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } */ |
- Callable : 보면 알겠지만 리턴값을 지정할수 있고 call() 로 실행한다. 또 에러처리를 할수 있어서 쓰레드실행시에 문제가 생겼을때 사용자가 적절한 처리를 할수있다.
- Runnale : run으로 실행한다.
Executor Framework는 자바 1.5 부터 제공해주는 것으로 기존의 단순 Thread 를 프레임워크화 해서 좀덛 쓰레드를 유연하게 사용하도록 해 준다.
대표 기능으로 thread pool, 생명주기 관리, Task 관리, 병렬처리(?), 비동기(Future)처리지원 등이다.
아래는 Future를 사용한 비동기 처리 예제이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | static class MyCallable implements Callable<String> { CountDownLatch howMuchCounting; String s = ""; @Override public String call() throws Exception { howMuchCounting.countDown(); return "http://ohmy.god?" + s; } public void setS(String argS) { s = argS; } public void setCountDowner(CountDownLatch argHowMuchCounting) { howMuchCounting = argHowMuchCounting; } } private void runExe() { CountDownLatch howMuchCounting = new CountDownLatch(3); ExecutorService mPool = Executors.newFixedThreadPool(5); List<String> yourInputDatas = Arrays.asList("page=1", "page=2", "page=3"); List<Future<String>> futures = new ArrayList<Future<String>>(); for (final String dataItem : yourInputDatas) { MyCallable myCallable = new MyCallable(); myCallable.setS(dataItem); myCallable.setCountDowner(howMuchCounting); futures.add(mPool.submit(myCallable)); } // 바로 아래의 await로 쓰레드가 모두 실행될때까지 기다린다. try { howMuchCounting.await(); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } // 모두 끝났으면 셧다운 mPool.shutdown(); List<String> results = new ArrayList<String>(); for (Future<String> future : futures) { // future에 있는 데이터는 그래도 사용 하기 번거로우니까 따로 담는다. try { results.add(future.get()); } catch (ExecutionException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } for (String s : results) { Log.i("fure", s); } } /* fure: http://ohmy.god?page=1 fure: http://ohmy.god?page=2 fure: http://ohmy.god?page=3 */ |
CountDownLatch 클래스는 동시성관련 유틸 클래스로서 초기에 몇개의 쓰레드가 동시에 이루질수 있는지 지정하고, 쓰레드의 각 처리가 끝나는 순간 하나씩 countDown하여 0 이 될때까지 await 함수를 통해 비동기작업이 끝나기를 기다리게 해준다.
이를 이용하여 모든 쓰레드를 강제로 닫는 shutdown 을 사용해도 문제가 없도록 구현할수 있게 해준다.
0 comments:
댓글 쓰기