리팩토링 (Refactoring) 이란?



-소스코드 구조를 효율적으로 변경하면서, 기능이나 동작의 변화가 없도록 하는 작업.



Restructuring VS refactoring


-재구조화는 다시 설계를 하는 작업.

-리팩토링은 나름의 규칙을 가지고 수정하는 작업.
Þ일련의 작업 Process가 있음.

ex) Return을 빼고, 변수이름을 네이밍 룰에 맞추어 진행하며 함수이름을 변경



변수의 읽기 쓰기 분석 연습

int mySumVar = 0;


for(int i = 0; i<1024 ; i++)

  mySumVar mySumVar + i;


mySumVar 은 읽고 쓰며, i 읽기만 하고 있음을 알 수 있다.


읽고 쓰는 변수 => call by reference 으로 함수 추출 시 파라메터로 사용하면 됨.

읽는 변수 => call by value 으로 함수 추출시 파라메터로 사용하면 됨.

참고) 쓰는변수 => 함수 추출 시 return 을 쓰면 됨.




void MySubSumI(int I, int *mySumVar )

{

  sub(i, &mySumVar );

}


int mySumVar = 0;

for(int i = 0; i<1024 ; i++)

  MySubSumI(i, &mySumVar );





변수 제거 기법 알아 보기.

- 어떤 변수가 모두 read만 하거나 write만 하면 변수 제거가능!


- 당연히 알 수 있는 값을 또하나의 변수에 저장하는 변수제거 해보기

-> 원의 넓이, 사각형의 넓이등등


- 플래그 변수들 의심해볼 것!

for, while, if, switch 등의 반목문혹은 조건식에서의 플래그를 검토해볼 것




변수 제거 기법 – flag 변수 제거 방법

- 플래그 변수의 읽기접근을 모두 제거 가 가능한가 검토 해볼것!

-> 쓰기 접근만 남게되면 그 변수는 제거가능

-무조건 true, 혹은 false로 빠지지 않는지 검토해보기!
-> 조건식을 옮겨서 true/false 무조건 되는지검토 물론 코드로직은 동일해야함을 검토!


-플래그 변수 읽기대신, 다른 조건식을 대체할수있는 변수나 조건이있는지 검토할 것
만약 플래그와 같이 동시에 쓰기가 되는 변수가 있다면 그 변수를 이용해서 조건식으로 대체 하는 방법 사용.




플래그 변수 제거 해보기



char *getInputFromUserFile(File *myFile)

{

//입력값을 읽기 전, 읽는 중

int BEFORE = 0

int READING = 1

int my_word_flag = BEFORE;


char *word = nullptr;

int i = 0;

char inputC;


while (inputC = fgetc(myFile))

{

if (my_word_flag == BEFORE) //문자 읽기전

{

word = static_cast <char *>(malloc(sizeof(char)*WORD_SIZE));

my_word_flag = READING;

word[i++] = inputC;

}

else if (my_word_flag == READING) //문자읽는중

{

  word[i++] = inputC;

}

}

return nullptr;

}



아래는 답안입니다.
============>>>>>>>>

char *getInputFromUserFile(File *myFile)

{

char *word = nullptr;

int i = 0;

char inputC;

while (inputC = fgetc(myFile))

{

if (word == nullptr)

{

word = static_cast <char *>(malloc(sizeof(char)*WORD_SIZE));

word[i++] = inputC;

}

else

{

word[i++] = inputC;

}

 }

 return nullptr;

}


참고)

쉘로 나가지않고 외부 명령어를 실행하고싶은경우


ex)   :! mkcscope.sh

!를 붙여주고 쓰면된다.


파일열기 

:edit 

파일저장하기 

:write :save :update 

창분할 

:sp :vs 

탭페이지

:tabedit :tabnew :tabclose :tabnext :tabprevious 

탐색 기능 

:edit 

파일명인식 

gf 

파일 목록

:files 혹은 :ls 

인코딩 형식 

:set fencs=... 




파일 버퍼 관련 명령어

 :e 파일명

파일을 편집용으로 엽니다. 

파일명 모르면 tab을 누르면 현재 디렉터리 파일을 하나씩 보여줍니다. 

ctrl ^ 

이전파일을 엽니다 

:e # 

 

:[#]n 

여러 파일이 열려 있을 때, 다음 파일로 이동합니다.

#에 숫자를 넣으면 해당 숫자만큼 반복합니다. 

:[#]N 

:n의 반대 방향으로 이동합니다. 


vim에서 다른파일을 여는 명령어는 :e file이름 입니다.

이기능을 통해서 A라는 파일을 작업중 :e b.txt 명령을 통해 b.txt 를 열수있습니다.

단 여기서 이동전, 저장해놓고 꼭 갑시다~!


또 여기서 CTRL ^ 을 누르면 이전에 편집했던 A라는 파일로 왔다갔다 되돌아 갈 수 있습니다.





파일을 저장하는 다양한 명령어

 :w filename

파일을 저장합니다 

:sav filename 

현재 파일을 다른 이름으로 저장합니다. 

:up 

변경 사항이 있는 경우에만 저장합니다. 

:x 

vim을 종료하면서 변경사항이 있는 경우에는 저장합니다. 





창분할 명령어 정리

 #sp [파일명]

상하로 창을 분할합니다. 파일명을 생략하면 현재 파일을 의미합니다. 

 #vs [파일명]

좌우로 창을 분할합니다. 

 #new 

상하로 분할하고, 위쪽에 새로운 창을 만듭니다. 

 #vnew 

좌우로 창을 분할하고, 왼쪽에 새로운 창을 만듭니다. 






창사이클 이동하는 명령어

 ctrl-W ctrl - 방향키

ctrl - w 방향키

방향키에는 h, j, k, l이나 화살표 키를 사용할 수 있습니다. 

 

 

 

 





분할된 창의 크기를 조정하는 명령어

 ctrl-W = 

모든창의크기를 동일하게 조정합니다. 

 

 

 

 





탭으로 열기

:tabedit hello.c


새파일을 탭으로 열고 싶다면 

:tabnew 파일이름 을 사용하면됩니다.


탭을 닫고싶다면

:tabclose





탭이동명령

 [#]tabn

다음 탭으로 이동하며, 일반모드의 gt와 동일 

 [#]gt 

#에 숫자를 지정하면 탭번호가 지정 

 [#]tabp[revious] 

이전탭으로 이동하며 일반모드의 gT와 동일 

 [#]gT 

#에 숫자를 지정하면 반복수가 지정됩니다. 

 :tabm[#] 

#번째 탭으로 현재탭을 이동시킵니다. (0부터 시작)

#이 생략되면 가장 오른쪽으로 이동시킵니다. 

 

 

 

 






탭 생성과 종료 명령

 :[#]tabe

#번째 탭에 파일을 엽니다. #을 생략되면 현재 탭 뒤에 생성됩니다.

번호는 0부터 시작합니다. 

 :[#]tabnew 파일명 

#번째 위치에 비어있는 탭을 만듭니다.

 :[#]tabc 

#번째 탭을 닫습니다. #을 생략하면 현재 탭을 닫습니다. 




VIM 디렉토리 탐색하기

윈도 탐색기처럼 vim에도 디렉토리 리스트를 보면서 파일을 선택할 수 있습니다.

netrw라는 기능이 있습니다. 기능은 간단히 :e directory 로 실행하면 됩니다.


예를 들어 :e . 명령은 






netrw의 주요 단축키

 <Enter>

파일을 현재 창에 열어 줍니다. 

 i

파일표시 방법을 변경합니다. 

 s 

정렬 방식을 바꿔줍니다(이름순, 시간순, 크기순) 

 o 

커서 위치의 파일을 수평분할된 새창으로 열어줍니다. 

 v 

커서 위치의 파일을 수직 분할된 새창으로 열어줍니다. 

 p 

커서 위치의 파일을 미리보기 창으로 열어줍니다. 

 P 

커서위치의 파일을 바로이전에 생성한 창에 열어줍니다. 

 R 

파일명을 바꿉니다 

 t 

새로운 탭으로 분할아여 열어줍니다. 

 - 

상위 디렉터리로 이동합니다. 





버퍼 목록에 표시되는 기호

 %

현재 편집중인버퍼 

바로이전에 열었던 버퍼 혹은 다음에 열도록 예비된 버퍼<CTRL-^>를 누르면 #이 표시된 파일이 열립니다. 

활성된 버퍼(현재 화면에 보이는 버퍼) 

창 분할 기능을 쓰는 경우에는 여러 파일에 a표시가 나타납니다.

변경된 부분이 있는 버퍼 






버퍼 관련 명령어들

 :ls

 파일 목록을 확인합니다. 

 :buffers 

 

 :files 

 

 :n {pattern} 

지정된 pattern으로 파일을 검색하여 목록에 추가하고 첫번째 검색된 파일을 열어줍니다. 

 {N} CTRL-^ 

{N} 번째 파일 목록을 엽니다. 

 :e #{N} 

 

 :Of 

현재 버퍼를 목록에서 제거합니다.

연결된 파일이있다면 해제하여 [No name]버퍼로 만듭니다. 

 :r 파일 

파일을 끼워 넣습니다. 






본문의 파일명을 인식해서 열어주는 명령어

 gf

커서 위치의 파일명을 인식해서 열어줍니다. 

 <CTRL-W> f 

커서 위치의 파일명을 분할된 창에 열어줍니다. 

 <CTRL-W> gf 

커서 위치의 파일명을 탭에 열어줍니다. 






문자열 정렬 

:center , :right

문자 검

fc 

문자열 검색 

/문자열 

단어 즉시검색 

* 혹은 ? 

문자열 교체 

:[range]s/찾을문자열/교체할문자열/옵션 

특수문자입력 

ctrl-V,문자 혹은 ctrl-Q,문자 




문자 검색 기능

 fc  혹은 /c

문자 c를 전방 검색 

 Fc 

문자 c를 후방 검색 

 tc 

문자 c를 전방검색하여, 검색어의 한칸 앞으로 이동 

 Tc 

문자 c를 후방검색하여, 검색어의 한칸 뒤로 이동 

 ; 

가자 ㅇ최근에 검색한 명령을 재검색 

 , 

가장 최근에 검색한 명령을 반대 방향으로 재검색 


검색 결과 하이라이트 기능 설정

:set hlsearch

검색 결과 하이라이트 기능 해제

:set nohlsearch



검색 후 이동 명령어

 n

다음 검색 결과로 이동 

 N 

반대 방향의 검색 결과로 이동 




교체 명령 옵션

g

범위내에 검색된 모든 문자열을 교체 

대소문자 무시 

문자열을 교체하기전 교체여부를확인 

교체과정중 에러 무시. 에러메시지 표시도 안함. 




문자열 교체에서 확인 입력의 의미

y

교체를 허용 

교체를 거부 

앞으로 남은 모든 교체 실행 

교체 작업 끝냄 

현재 행의 교체 작업만 하고 교체작업 끝냄 

^E 

아래로 한행 스크롤하여 보여줌 

^Y 

위로 한행 스크롤하여 보여줌 


vim 옵션



옵션상태 확인하기



:set all    // vim 에서 사용하는 모든 옵션을 보여줌

:set       // 현재 설정도니 주요 옵션들만 간략하게 볼 수 있음.


<스크린샷>

no가 앞에 붙은옵션은 현재 비활성화 상태.

no가 붙지않은 것들은 활성화 상태



set명령어 사용법


 :set

현재 옵션 설정을 보여줍니다. 

 :set all 

모든옵션 설정을 보여줍니다. (off 상태의 옵션까지 모두 출력) 

 :set [no]name 

name 에 해당하는 옵션을 켜거나 끕니다. 앞에 no를 붙이면 off 상태가 됩니다. 

 :set name! 

name 옵션의 on, off 상태를 전환(toggle) 합니다. 

 :set name=value 

name에 해당하는 옵션에 value 값을 할당합니다. name만 지정하면 해당옵션의 value 값을 보여줍니다. 


ex_

:set ai!  옵션이 켜지고 꺼지고 반복.

:set name=value 형식으로 명령하기도함.

:set ts=4 ts옵션에 4를 지정

:set ts  현재 ts값을 보여줌.




편집에 관련된 기초 옵션들

 nu (number)

화면에 행번호표시 

 ai (autoindent) 

자동 들여쓰기를 사용합니다 

 cindent 

C언어 스타일의 들여쓰기를 사용합니다 

 ts=value 

탭 크기를 value로 지정 

 sw=value 

블록 이동시 열의 너비 

 tw=value 

편집할 화면의 열 길이를 정합니다. 



행번호 출력 옵션


:set nu     // 행번호가 나옵니다.




:set nonu   // 행번호를 끕니다      ( 혹은 set nu!, 이런식으로 토글 전환가능)



탭 크기 옵션

:set ts=4    // 탭크기 조절

:set sw=4   // 블록 시작시 자동으로 들여쓰는 길이 설정 함.



옵션과 색상 테마 저장하기 (VIM 설정 파일)


vim이 종료되면 설정했던 옵션이 모두 초기화 됩니다. 옵션을 파일로 저장해두면 사용하기 편하겠죠~?

vim 설정 파일도 홈 디렉토리에 .vimrc 라는 이름으로 만들어 두면 됩니다. 



설정파일 만들기

vim을 실행한후


:e ~/.vimrc 라고 명령해봅니다.


그리고 아래와 같이 nu 설정과, ts sw 값을 설정합니다.

그리고 다시 vim을 켜면 설정한대로 적용됨을 확인하실 수 있습니다.




문법 오류 표시


c언어를 사용하는데 일부로 틀리게 되었을때 눈에 표시가 되면 개발하기 정말 편하겠죠~?

이를 위한 기능이 vim에서 지원되고있습니다.



일부로 틀리게 입력해봅니다. printf에서 "를 하나 뺐습니다.




역시 잘 티가 안나는군요.

이번에 문법 표시를 켜봅시다.

그다음 
:syntax enable 로 문법표시를 사용해서 켜보면 됩니다.



 :syntax enable

문법 표시를 사용합니다. 

 :syntax clear 

문법 표시를 사용하지 않습니다. 



문법 표시기능이 활성화 되면(syntax enable) 여기에 색상 테마를 입힐 수 있습니다.

이때 사용하는 명령이 

:colorscheme 입니다.



색상테마


 :colorscheme <scheme>

 <scheme> 색상을 사용합니다. 



아래와 같은 <scheme> 들이 있습니다.

 blue

밝은청색 

 darkblue 

어두운 청색 

 default 

기본값 

 delek 

청색과 녹색 게열 

 delek

청색과 녹색 계열 사용

 desert

모래색 게열 사용 

 elflord 

흰색, 밝은 자주색 계열 

 evening

저녁 분위기에 알맞은 밝은 색 게열을 사용합니다. 

 koehler 

elflord와 비슷하지만 좀더 대조적인 색상을 사용합니다. 

 morning 

회색톤 계열을 사용합니다 




에러처리

vim에서 같은 파일을 또다시 열면 이상한경고 화면이 나타납니다. 

이 경고 화면의 복잡한 메시지 때문에 당황하는 경우가 있습니다. 


파일 중복열기에러


일부로 파일중복열기 에러를 발생시켜보겠습니다.

어떤 파일을 작성도중에 CTRL+Z로 눌러서 빽그라운드로 돌리고 터미널로 돌아와봅시다.


그다음 다시 같은 파일을 편집하로 들어가봅니다.


stopped 앞에 나온 번호는 작업번호입니다. 이 작업번호를 이용해서

터미널에서 

fg %작업번호 라고 명령하면 정지된 작업을 다시 불러올 수 있습니다.

fg %1 하면(여기서는) 다시작업을 불러오게됩니다.


그런데 동일한 파일을 또 열려고하면 vim은 경고 메세지를 보여줍니다. 




사실 vim 에서 파일을 열면 스왑 파일을 하나 생성합니다. 생성된 스왑파일은 파일명 앞에 마침표(.) 하나 붙여서 숨김 파일로 만들고, 뒤에는 .swp의 확장자 명을 붙입니다. 이파일은 undo 용도로 사용되는데, vim이 정상종료되면 자동 삭제가 됩니다.


뭐 어쨌든, 다시 vim 파일을 열게되면 이 스왑 파일을 만들어야 하는데, 이전에 vim이 종료되지않았기때문에 스왑파일을 만들지 못해 에러가 발생합니다.


그래서 다섯가지 해결방법을 제시합니다.

단축키 O, E, R, Q, A 를 사용합니다.


뭐 저같은경우는 그냥, 

$ rm .파일명.swp    이런식 스왑파일을 지운뒤 다시 vim을 켜서 작업을 진행합니다.




Q나 A는 아무런 작업하지 않고 vim을 종료하는 기능인데 A의 경우는 디버깅용 덤프파일을 생성하는 점이 다릅니다.

VIM 을 설치해봅시다.


VIM은 리눅스에서 가볍고 기능도 엄청난 최강의 Editor라 할 수 있습니다.


$ sudo apt-get install vim 을 통해 설치해줍시다.


위명령을 치면 간단하게 설치가 됩니다.



우선 vim을 실행하기전에 간단한 기능을 살펴보겠습니다.


파일 저장하기

:w

종료하기 

:q 

커서이동 

h, j, k, l 

삭제 

x, dd, J 

복사 

yy 

붙이기  

명령어 취소(undo) 

범위 지정(블록) 




리눅스에서 vim을 실행하면, 일반모드 상태로 시작됩니다. 

이상태에서는 키보드를 아무리쳐도 입력이안되는데요. 입력모드로 전환해줘야합니다. 입력모드 전환키는 i입니다.


그러면 밑하단을 보시면 입력모드로 바껴있음을 확인하실 수 있습니다.

입력모드는 입력만을 위한 모드이므로, 저장하려면 입력모드를 끝내야합니다.

ESC를 누르면 입력모드를 끝내고 일반 모드로 돌아오게됩니다.


여기서 :를 누르고 w를 누르고 엔터치면 파일이 저장됩니다.

:w teset.txt

test.txt 라는 파일로 저장하게 됩니다.








파일을 저장하고 종료하려면 

:q   


또한, 저장하고 종료를 바로하려면

:wq

로 입력하면 됩니다.



저장과 종료 명령어

:w

 write 현재 파일저장 

:q 

quit, vi를 종료 

:wq 

w와 q의 조합으로저장하고 종료 

:w filename 

filename에 해당하는 파일에 저장한다 

:q! 

변경된 내용을 버리고 vi를 종료 (강제종료) 

:w! filename 

filename에 해당하는 파일을 덮어쓴다 

:wq! filename 

filename에 해당하는 파일을 덮어쓰고 종료한다. 



커서 이동키

^

행의 맨앞으로 이동(공백제외) 

행의 맨끝으로 이동 




화면 스크롤 하기


Ctrl + B , Page up 

 위로 한 화면 스크롤 

Ctrl + F,  Page Down 

 아래로 한 화면 스크롤 





문서 특정 위치로 이동하기

:# 

#G

#행으로 이동합니다. 

#행으로 이동합니다.




현재 위치 확인하기

Ctrl + g 

  현재 문서 위치정보를 하단 상태바에 표시합니다.




삭제하기


 dd

현재 행을 삭제 

 D 

현재 컬럼 위체에서 현재 행의 끝부분까지 삭제 



붙여넣기


vim에는 지우는 기능이 없다고 해도 무방합니다.

지웠던것은 레지스터에 남아서 p로 붙여넣기를하면 d로지웠던 내용들이 붙여넣기가 됩니다.!


 p

현재 행에 붙여 넣습니다. 



복사하기

y는 뽑아낸다는 뜻으로 yank 의 약자입니다.

yy 

현재 행을 레지스터에 복사합니다. 



작업 취소하기

 u

undo 기능입니다. 바로 이전에 행한 명령 하나를 취소합니다. 

ctrl - R 

redo 기능입니다. 바로이전에 취소했던 명령을 다시 실행합니다. 



범위 지정에 쓰이는 특수 기호

 .

현재행을 의미 

마지막행을 의미 

+# 

현재위치에서 #만큼 아래행 

-# 

현재위치에서 #만큼 위행 의미 

문서(파일) 전체를 의미 

.



범위지정하기

 :20d

20번 행을 삭제 

:10, 25d

10~25번 행 삭제 

 :10, $d

10~마지막 행까지 삭제 

:%y 

문서 전체 복사.  

:.,+20y

현재행부터 아래로 스무행 복사 

:-10, +5d 

현재행위로 10행, 아래로 5행 총 열여섯 행 삭제 

:40pu 

40행에 레지스터 내용 붙여넣기 




비주얼모드

 v

 일반 비주얼 모드로 현재 커서 위치에서 블록을 지정합니다. 

 V

 비주얼 라인 모드로, 현재커서가 위치한 행에서 행단위로 블록을 지정합니다. 

 Ctrl + V

 비주얼 블록모드롸, 열 단위로 블록을 지정합니다.  




비주얼 모드에서 커서 이동하기

v를 누른후, 20G 를 누른다면

현재행에서 20 라인까지 블록선택이 됩니다.~! 문서 끝까지 입력하려면 G를 누르면 됩니다.!!!!







저번 포스팅에선 우분투에 타이젠 개발환경을 세팅했습니다.


하지만 윈도우에서 작업할게 많은 현대인? 들 특성상, 윈도우에서 우분투에 접속하여 터미널 명령을 치고싶은경우가 있습니다.


putty도 있겠지만 저는 좀 특별하게? supperputty라는 것을 이용해볼겁니다.


탭기능이 있어서 터미널을 여러개 뛰워놓고 작업하기가 정말 강력하거든요 ㅎㅎ




아래싸이트에 접속하여 다운받습니다.


https://github.com/jimradford/superputty/releases






자 superputty 설치가 끝났으면 우분투 쪽에 설정을 하러갑시다.

윈도우 -> 우분투 터미널접근을하려면 ssh를 뚫어놓아야 합니다.


$ sudo apt-get install ssh



설치가 완료되면 SSH 서버를 상시로 사용하기 위하여 서비스 명령을 사용해줍시다.

$ sudo systemctl enable ssh



서비스 실행중인지 확인해봅시다.
$ sudo systemctl start ssh
$ sudo systemctl status ssh

포트변경

$ sudo vim /etc/ssh/ssh_config

port 22에서 #를 제거하고 원하는 포츠로 변경하시면되겠습니다.




자이제 super putty 를 여시고, 오른쪽 putty Sessions에서 세션을 추가합니다. (오른쪽마우스 - new)






짜잔~! 윈도우 super putty 에서 원격 우분투로 터미널 접속을 하였습니다!


이제 윈도우 원격 터미널로도 타이젠 개발을 할 수있겠군요 ㅎㅎㅎ




putty 설정은 아래사이트를 참고해서 하면 편하십니다.


http://blog.naver.com/PostView.nhn?blogId=debolm74&logNo=221040869520&parentCategoryNo=&categoryNo=50&viewDate=&isShowPopularPosts=false&from=postView



putty 세션유지는 아래사이트를 참조하시면 됩니다.


http://overegoz.tistory.com/719


우분투에 처음부터 타이젠을 설치해보고 개발환경을 갖추어 보도록 하겠습니다.



우분투 환경에서 아래의 Tizen 공식 사이트에 접속합니다.


https://developer.tizen.org/development/tizen-studio/download


Tizen Studio 2.2 with IDE installer 를 다운로드받습니다.





해당파일을 다운받은 곳으로 가서


$ sudo chmod +x web-ide_Tizen_Studio_2.2_ubuntu-64.bin     //실행 속성 부여

$ ./web-ide_Tizen_Studio_2.2_ubuntu-64.bin                      //실행하기


라 입력했는데 아래와 같이 뜨면 JDK를 설치해주면됩니다.



아래 명령어는 현재 default로 설정된 자바를 설치합니다.

$ sudo apt-get install default-jdk $ sudo apt-get install default-jre



자 다시 설치를 진행합니다.~!

$ ./web-ide_Tizen_Studio_2.2_ubuntu-64.bin   



accept 하고 install합니다.


그런데 또 다음과 같이 뜨네요 ㅎㅎ


그렇다면 또 명령을 터미널에서 쳐줍시다.



$ sudo apt-get install libwebkitgtk-1.0-0

$ sudo apt-get install rpm2cpio




설치를하고나서 다시 install 버튼을 누르면 설치가 진행되는것을 보실 수 있습니다.


그다음에 finish 를 누르다보면 Package Manager 라는게 뜨게됩니다.


저는 4.0 Wearable 이랑, Tizen SDK Tools를 설치했습니다.

install을 눌렀는데 또 뭘 설치하라고하면 그 명령 그대로 입력하여 설치하시면 되겠습니다.~!







타이젠 스튜디오를 실행해봅니다.

이클립스기반이라 이클립스랑 UI가 비슷하네요 ㅎㅎㅎ




OK를 누르고 넘어갑니다.

아래와 같이 Tizen Studio 가 설치되었음을 확인했습니다  굿굿 ㅎㅎ 이제 신나는 타이젠? 개발을 할 수있는 환경을 갖추었군요 ㅎㅎㅎㅎ






Thread (스레드) 설정

ThreadPoolExecutor는 작업자 스레드 개수와 풀의 생성과 종료뿐만이 아니라, 모든 스레드의 속성도

정의한다.  흔히 설정하는 응용프로그램 동작은 UI스레드와 경쟁하지않도록 스레드 우선순위를 낮추는 것이다.



작업자 스레드는 ThreadFactory 인터페이스의 구현을 통해 설정된다. 스레드 풀은 우선순위,이름,

예외 핸들러와 같은 작업자 스레드의 속성을 정의할 수 있다.



Thread 속성을 customize 한 고정 스레드풀



class LowPriorityThreadFactory implements ThreadFactory{
private static int count = 1;

public Thread newThread(Runnable r){
Thread t = new Thraed(r);
t.setPriority(4);
t.setUncaughtExceptionHandler(new Thraed.UncaughtExceptionHandler(){}
@Override
public void uncaugghtException(Thread t, Throwable e){
Log.d(TAG, "Thread = "+t.getName() + ", error="+e.getMessage());
});
return t;
}
}

Executors.newFixedThreadPool(10, new LowPriorityThreadFactory());




스레드 풀은 많은 스레드를 가지고 있고, 그 스레들은 실행시간을 두고 UI 스레드와 경쟁하기 때문에,

일반적으로 작업자 스레드에는 UI 스레드보다 낮은 우선순위를 할당하는 것이 좋다.


우선순위가 커스텀 ThreadFactory보다 낮지 않은 경우, 작업자 스레드는 기본적으로 UI 스레드와  같은 우선순위를 얻는다.



ThreadPoolExecutor 확장

ThreadPoolExecutor는 주로 독립적으로 사용되지만, 프로그램이 실행자 또는 실행자의 태스크를 추적할 수 있도록 확장될 수 있다. 응용프로그램은 스레드가 실핼될 때 마다 취하는 동작을 추가하기 위해 다음 메서드를 정의할 수 있다.



void beforeExecute(Thread t, Runnable r)

스레드를 실행하기전에 런타임 라이브러리에 의해 실행된다.



void afterExecute(Runnable r, Throwable t)

스레드가 정상적으로 또는 예외에 의해 종료된 후 런타임 라이브러리에의해 실행된다.


void terminated()

스레드 풀 종료 후 실행중이거나 실행을 위해 대기중인 태스크가 없을떄 런타임 라이브러리에 의해 실행된다.




처음 두메서드에는 Thread와 Runnable 객체가 전달된다. 전달되는 순서가 두 메서드에서 반대라는 점에 유의해라.

스레드 풀에서 얼마나 많은 태스크가 현재 실행되는지 추적하는 기초적인 커스텀 스레드 풀을 보여준다.



스레드 풀에서 진행중인 태스크의 수를 추적하는 예제 code


public class TaskTrackingThreadPool extends ThreadPoolExecutor{

private AtomicInteger mTaskCount = new AtomicInteger(0);

public TaskTrackingThreadPool(){
super(3, 3, 0L, TimeUnit.SECONDS, new LinkedBlockingQueue());
}
@Override
protected void beforeExecute(Thread t, Runnalbe r){
super.beforeExecutor(t,r);
mTaskCount.getAndIncrement();
}

@Override
protected afterExecute(Runnable r, Throwable t){
super.afterExecute(r,t);
mTaskCount.getAndDecrement();
}

public int getNbrOfTasks(){
return mTaskCount.get();
}


}



beforeExecute는 태스크 실행전에 mTakseCoutner를 증가시키고 afterExecute는 실행후에

카운트를 감소시킨다. 


외부 관찰자는 언제든 getNbrOfTasks를 통해 현재 실행 태스크의 수를

요청할 수 있다. 


작업자 스레드와 외부 관찰자 스레드는 동시에 공유멤버변수를 접근할 수 있다.

따라서 스레드 안전을 보장하기 위해 AtomicInteger로 정의했다.



커스텀 스레드 풀


ThreadPoolExecutor 설정


ThreadPoolExecutor에 의해 스레드의 생성과 종료뿐만 아니라 Task의 큐잉에도 사용되며 다음과 같은 생성자에서 수행된다.



 ThreadPoolExecutor executor = new ThreadPoolExecutor(

   int corePoolSize, //핵심풀크기

   int maximumPoolSie,  //최대풀크기

   long keepAliveTime,  //생존 유지시간

   TimeUnit unit,  //생존 유지 시간의 단위

   BlockingQueue workQueue; //태스크 큐 유형

);




핵심풀 크기

스레드 풀에 포함되는 스레드의 하한, 실제로 스레드풀은0개 스레드로부터

시작하지만, 핵심 풀 크기에 도달하면 스레드 개수는 하한 이하로 떨어지지않는다.

풀에서 작업자 스레드의 개수가 핵심 풀크기보다 적을때, 태스크가 큐에 추가되면, 작업을 기다리는 유휴스레드가 있는경우에도 새로운 스레드가 생성될 것이다. 일단 작업자 스레드의 개수가 핵심풀크기보다 같거나 많아지면,

큐가 가득찬경우 새로운 작업자 스레드가 생성된다. 즉 큐는 스레드 생성에 대한 우선권을 얻는다.



최대 풀 크기

동시에 실행할 수 있는 스레드의 최대개수.

최대 풀 크기에 도달한 후, 큐에 더해진 태스크는 태스크를 처리할  유휴 스레드가 사용가능해질 떄까지 큐에서 기다린다.



최대 유휴시간(생존 유지시간)

유휴 스레드는 처리하기 위해 들어오는 태스크를 준비하기 위해 활성 상태를 유지하지만, 생존시간이 설정된 경우 시스템은 비핵심 풀 스레드를 회수할 수 있다.

생존시간은 TimeUnit에 의해 설정된 시간 단위로 측정된다.



태스크 큐 유형

Task가 작업자 스레드에 의해 처리될 수 있을때까지 소비자에 의해 더지핸 Task를 보유하는 BlockingQueue의 구현.



- 스레드 풀 설계

스레드 풀은 동시에 백그라운드 Task를 실행해야 하는 스레드를 관리하는데 

도움을 주지만, 사용자는 여전히 제한된 자원 소비와 높은 처리량을 얻기 위해 현명하게

설정해야 한다. 기본적인 목표는 필요한 것보다 더 많은 메모리를 사용하지 않고

하드웨어에 의해 허용되는 가장높은 속도로 작업을 처리하는 스레드 풀을 생성하는 것이다.




크기나스레드풀의 최대크기를 정한다. 스레드의 최대 개수가 너무작으면

충분한 속도로 큐에서 태스크를 꺼내지않아 성능저하될수있따.


예를들어 모든 스레드가 긴 I/O연산을 실행하는 경우, I/O 동작이 완료될떄까지 실행시간을 얻지 못하고 

기다리는 짧은 수명의 태스크가 있을 수 있다.


반면 너무 많은 스레드도 CPU가 실행 대신 스레드의 전환에 많은 시간을 사용해야하므로 성능에 부정적인 영향을 미칠 수 있다.


스레드 풀의 크기는 하부의 하드웨어, 좀더 정확히말해 사용가능한 CPU 개수를 기준으로 하는것이 좋다. 안드로이드는 Runtime 클래스에서 CPU개수를 알아낼 수 있다.


int N  = Runtime.getRuntume().availableProcessors();


N은 실제로 동시에 실행될 수 있는 태스크의 최대 개수다.


스레드 풀의크기 N은 독립적이고 비차단적인 태스크들의 운용하기에 충분할수있다.

(고도의 연산을 요하는등)



역동성



제한 또는 무제한 태스크 큐

스레드풀은 일반적으로 제한 또는 무제한 태스크 큐와 함꼐 사용한다.

무제한 큐는 무한증가할 수 있어서 메모리가 고갈할 수 있는 반면, 제한 큐의 자원소비는

더 잘관리될 수 있다 한편 제한 큐는 그 크기와 포화정책을 모두 준비해야하낟.

포화정책이란 거부된 태스크를 생산자가 어떻게 처리할지를 뜻한다.



제한 또는 무제한의 큐를 구현한 것이 LinkedBlockingQueue, PriorityBlockingQueue, ArrayBlockingQueue다.

뒤의 두가지 큐는 제한 큐고, 첫번째 큐는 기본적으로 무제한 큐지만 제한 큐로 구성할 수 있다.


스레드 풀


Thread pool은 task 큐와, 작업자 스레드 집합의 조합.


작업자 스레드는 생산자-소비자 구조를 형성한다.


생산자는 큐에 Task를 추가하고, 작업자 스레드는 새로운 백그라운드 실행을

수행할 준비가 된 유휴 스레드가 있을 때마다 Task를 소비한다.




작업자 스레드 풀은, 태스크를 실행하는 활성 스레드와 실행을 기다리는 유휴 스레드를 모두포함할 수 있다.



스레드 풀의 장점

- 작업자 스레드는 실행할 다음 태스크를 기다리기 위해서, 살아 있을 수 있음. 이는

스레드가 매 태스크를 위해 생성과 파괴(오버헤드 증가)될 필요 없다는 것을 의미한다.


- 스레드 풀은 스레드의 최대개수로 정의된다. 이는 응용프로그램 메모리를 소비하는

백그라운드 스레드 수가 많아져서 스레드 풀에 과부하가 걸리는것을 막기 위해서다.


-모든 작업자 스레드의 생명주기는 스레드 풀 생명주기에 의해 제어된다.



미리 정의된 스레드 풀

Executor 프레임워크는 Executors 팩토리 클래스에서 만들어진 미리 정의된 스레드 풀 유형을 포함한다.


- 고정 크기

고정크기 스레드 풀은, 사용자가 정의한 개수의 작업자 스레드를 유지한다.

종료된 스레드는 작업자 스레드의 일정 스레드 수를 유지하기 위해 새로운 스레드로 대체딘다.

고정된 풀 유형은 Executors.nexFixedThreadPool(n) 으로 생성되며 n은 스레드 수다.


이 스레드 풀 유형은 무한한 태스크 큐를 사용한다. 즉 새로운 태스크가 추가로 더해지면 큐가 자유롭게 증가할수있다.

그러므로 생산자는 태스크를 삽입하는데 실패하지 않는다.



- 동적 크기

동적 크기의 스레드 풀, 즉 캐시된 스레드 풀은 처리할 태스크가 있을 때 새로운

스레드를 만든다. 유휴 스레드는 실행할 새로운 태스크를 60초간 기다리고, 태스크 큐가 비어있는

경우 종료된다. 따라서 스레드 풀은 실행할 태스크 수와 함꼐 늘어나고 줄어든다.

Executors.newCachedThreadPool()로 생성한다.




- 싱글스레드 실행자

이 풀은 큐에서 task를 처리하기위해 하나의 작업자 스레드를 가진다.

태스크는 차례대로 실행되고 스레드 안전이 침해될수없다.

Executors.newSingleThreadExecutor()로 생성한다.

+ Recent posts