규칙 68 - 스레드보다는 실행자와 태스크를 이용하라.

JAVA/Effective Java|2018. 6. 13. 09:35

여러 쓰레드를 실행해야할 때,  큐에 넣고 작업을 진행하거나 할 수 있으면 더욱 효율적으로 관리 할 수있다.


그래서 자바 1.5부터 자바 플랫폼에는 java.util.concurrent가 추가되었다. 이 패키지에는 Executor Framework가 들어 있는데 이는 인터페이스 기반 task 실행 프레임워크이다.


해당 Executor를 실행하기 위해서는 다음과 같이 입력하면 된다.

1
2
3
4
5
6
7
ExecutorService executor = Executors.newSingleThreadExecutor();
    executor.    
    @Override
    public void run() {
        System.out.println("test");
    }
});
cs


그리고 만약 executor안에 요소가 모두 실행이 끝난뒤에는 실행자가 꺼지지는 않는다.

이를 명시적으로 꺼주어야 하는데 그때 shutdown() 메소드를 이용하면 된다.


이른 기능을 제외하고도 임의에 task의 작업을 기다릴 수도 있고 task가 끝날때마다 정보를 가져오도록 할수도 있다. 


여러 작업을 관리해야하는 경우에는 ThreadPool을 만들어서 작업할 수 있다. 이런 작업을 제공하는 ThreadPool은 newCachedThreadPool과 newFixedThreadPool이 있다.


먼저 newCachedThreadPool은 부하가 크지않고 작은 프로그램에서 사용하기에 적합하다. 설정도 필요없고 보통 많은일을 알아서 처리한다. 하지만 작업량이 많은곳에서는 적합하지 않다. 

왜냐하면 해당 쓰레드풀은 작업이 큐에 들어가는 것이 아니라 실행을 담당하는 스레드에 바로 넘겨진다. 그렇기 때문에 task가 많이 지정될 경우에는 상당히 많은 양의 쓰레드가 생성이 되어 CPU의 사용량이 증가된다.


그렇기 때문에 이를 보안하는 ThreadPool이 있는데 newFixedThreadPool이다.


newFixedThreadPool은 스레드 개수가 고정된 풀을 만들어서 제어가 손쉽다.


이런 실행자들을 이용하여 쓰레드를 관리하면 별도의 개별쓰레드를 만들어서 관리하는 것보다 훨씬 편하고 안정적이다.


  출처 : 조슈아 블로크, 『 Effective Java 2/E』, 이병준 옮김, 인사이트(2014.9.1), 규칙68



댓글()

규칙 67 - 과도한 동기화는 피하라

JAVA/Effective Java|2018. 6. 10. 21:17

동기화 시에 너무 많은 동기화 블록을 사용할 경우에 데드락이 걸리거나 성능저하 등등 문제를 일으킬 수 있는 소지들이 몇 가지 있다.


특히 동기화 영역안에서 수행되는 작업의 양을 가능한 줄여야 한다.


자바에서는 동기화에 대한 비용처리가 그나마 잘되어있지만 잘 사용해야 하는 이유는 잘못된 동기화 사용은 각 쓰레드들의 메인 메모리 접근에 대한 지연시간을 늘릴 수 있기 때문에 비용이 증가할 수 있다.


또한 클래스 내에서 동기화를 수행하는 것이 외부에서 객체 호출 시 사용하는것 보다 높은 병행성을 달성 할 수 있을 때문 진행해야한다.


다시말하자면 필요할 때 해당 메서드등을 호출하여 동기화를 실행해야지 해당 메서드 자체를 동기화 하는것은 좋지 않다. 예를 들면 기존에는 StringBuffer를 사용하여 내부적으로 Thread-safe하게 동작하여 많이 사용하였지만 굳이 병렬성을 보장하지 않아도 되는경우에도 자주 사용하여 문제가 자주 발생했다.


그래서 StringBuilder이 생겼고, 필요시에 동기화 블록을 만들어서 Thread safe하게 처리를 하였다.


그리고 


static 필드를 변경하는 메서드가 있을 때는 해당 필드에 대한 접근을 반드시 동기화 해야한다. 왜냐하면 해당 필드에 대해서 다른 쓰레드가 접근하고 있는지에 대해 알 수 있는 방법이 없기 때문이다. 


요약하자면 주의해서 동기화 블록을 사용하고 해당 내용에 대해서 문서에 정확히 적어주어야 한다.

문서에 해당내용을 잘 적지 않는 개발자들이 많다. 잘 적지 않고 알아서 코드를 보고 분석해서 그때그때 사용하기를 원하는 사람들을 일을 하면서 많이 보았다.


물론 같은 개발자로서 코드로 이야기 한다는 명목안에서 그럴 수 있지만, 일에 대한 처리가 순조롭지 않다. 그렇다면 본인들은 개발을 진행할 때 필요한 라이브러리가 있을 때 Document를 보지 않고, 코드를 모두 분석 후 사용하는지 묻고 싶다.. 


협력하는 시대에 협력하지 않고 구태적 마인드를 가지고 있다면 그는 효울적인 자바코드를 사용하는 근본이 잘못되었다고 생각한다.


 출처 : 조슈아 블로크, 『 Effective Java 2/E』, 이병준 옮김, 인사이트(2014.9.1), 규칙67

댓글()

피터 코드의 상속 규칙

상속의 오용을 막기위해 상속의 사용을 엄격하게 제한한다.
하위에 존재하는 규칙중 하나라도 만족하지 못한다면 상속을 하지 않아야한다.

1. 자식 클래스와 부모 클래스 사이의 '역할 수행' 관계가 아니어야 한다.
-> 요리사는 사람이라는 범주를 상속해서는 안된다. 
-> 요리사라는 것은 사람이라는 속성의 하나이다.

2. 한 클래스의 인스턴스는 다른 서브 클래스의 객체로 변환할 필요가 없어야 한다.
-> 엄마라는 객체는 누군가의 딸이라는 객체가 될 수 있다. 
-> 이런 속성 변경이 잦을 경우에는 객체의 변환 작업이 필요해서 해서는 안된다.

3. 자식클래스가 부모 클래스의 책임을 무시하거나 재정의하지 않고 확장만 수행해야 한다.

4. 자식클래스가 단진 부모클래스의 일부 클래스의 기능을 재사용하기 위한 역할로 클래스를 상속하지 말아야 한다.

5. 자식 클래스가 역할, 트랜잭션 등을 특수화 해야한다.

'IT 지식 > 소프트웨어 공학' 카테고리의 다른 글

프로그래밍 코드 작성 시 주요원칙  (0) 2018.05.30
피터 코드의 상속 규칙  (0) 2018.05.30

댓글()

javascript 기타 팁

web/javaScript|2018. 5. 27. 10:19

javascript tip 에 대한 좋은 글이 있어서 정리해 보았다.

https://m.blog.naver.com/tmondev/221070133735




1. css selector 우선순위
-> css Selector의 적용 우선순위가 있다.

해당 블로그에서 제공하는 자료에 보면 적용 우선순위는 다음과 같다.
!important > id > class > tag 




2. window.onload와 $(document).ready() 선언 차이

1) <script> 내에서 window.onload를 정의
- 전체 페이지의 모든 외부 리소스와 이미지가 브라우져에 불러진 이후에 실행됨

2) <body>에 onload 속성
- 1번과 마찬가지로 외부 리소스와 이미지가 모두 불러진 후 작동한다. 하지만 이걸 사용하게 되면 1번 방식은 아무리 선언해놨어도 무시당한다.

3) jQuery의 $(document).ready() ==> 가장 좋은 방법
- 외부 리소스 및 이미지 상관없이 DOM 요소들만 읽어 들이면 바로 실행된다. 여러가지 선언해서 사용할 수 도 있다.



1
2
3
4
5
6
7
8
<script type="text/javascript">
    $(document).ready(function(){
      
    });
    $(document).ready(function(){
      
    });
 </script>
cs



댓글()

Javascript 성능 저하에 조심 할 부분

web/javaScript|2018. 5. 27. 10:17

Javascript 성능을 저하시키는 부분에 대한 좋은 글이 있어서 

공부해보고 정리해 보았다.

=> 원본
https://m.blog.naver.com/tmondev/221070295102



1. 전역 변수 및 Element를 캐싱
=> 자바스크립트의 전역 변수는 스코프 체인의 마지막에 오게 되므로, 전역 변수 내의 태그 탐색 등의 일을 하게되기 때문에 n*2의 비용이 발생

=> 어떤 값을 찾을 때까지 스코프 체인 끝까지 뒤지기 때문에 성능에 문제가 발생할 수 있다는 뜻으로 해석됨.




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
/* 사례 1.
  document라는 javascript 전역 객체에 지속적으로 접근하기 때문에 해당 객체의 스코프 체인을 실행시키기 때문에
 문제가 발생하므로 doc 지역변수에 캐싱하여 사용
*/
# 문제상황
function problemFunction() {
  var data = document.getElementById('data');
  var data2 = document.getElementById('data2');
  var data3 = document.createElement('data3');
};
 
# 해결방법
function solutionFunction() {
  var doc = window.document;
 
  var data = doc.getElementById('data');
  var data2 = doc.getElementById('data2');
  var data3 = doc.createElement('data3');
};
 
 
/* 사례 2.
  jQuery를 사용할 때에도 변수를 이용하는 방식이 더 효율적
*/
# 문제상황
function problemFunction() {
  $(“#dataId”).val(“cjung”);
  $(“#dataId”).css(“display”, “NONE”);
  $(“#dataId”).attr(“checked”, true);
};
 
# 해결방법
function solutionFunction() {
  var data = $('#dataId');
 
  data.val(“cjung”);
  data.css(“display”, “NONE”);
  data.attr(“checked”, true);  
};
 


/* 사례 3.
  append child 할때도 다음과 같이 하는 것이 효율적
*/
# 문제상황
function problemFunction() {
  var data = document.createElement("data");
  opt.text = 'data is fun';
  $('#dataDiv').appendChild(opt);
};
 
# 해결방법
function solutionFunction() {
  var dataDiv = $('#dataDiv');
 
  dataDiv.append('<span>fdfdf</span>');
};
cs




2. javascript 문자열 조합 방식 성능 (concat, join)


1
2
3
4
5
6
7
8
9
10
function concatTest() {
  var str = "concat" + "is" + "goog";
}
 
function arrayTest() {
  var strArray = ["array", "is", "not good"];
  var str = strArray.join('');
}
 
// concat 보다 array join이 성능이 더 좋다고 알려졌으나 요새는 concat이 성능이 더 좋다.
cs




3. innerHTML과 appendChild
=> appendChilde는 element 개수만큼 매번 새로 할당하는 방식이고, innerHTML은 노드를 직렬화하여 개수만큼 만들어 한번만 할당하므로 innerHTML이 더 좋다.
-> 다만 이 두개의 차이는 만건 이상의 element를 새로 생성할 정도의 규모에서 차이가 발생한다.



1
2
3
4
5
6
7
8
9
10
11
12
13
function innerHTMLFunc() {
  var doc = document;
  var data = doc.getElementById('dd');
  data.innerHTML = "<span>" + 'dfdf' + </span>;
}
 
function innerHTMLFunc() {
  var doc = document;
  var data = doc.getElementById('dd');
  var span = doc.createElement('span');
  span.innerText = 'dfdf';
  data.appendChild(span);
}
cs


댓글()