작업을 하다 보면 여러 스레드들이 충돌하거나 다른 문제가 발생하는 가능성이 있다.
스레드는 프로세스 내부에서 진행되는 로직과 별개로 병렬로 실행되며
따라서 여러개의 스레드가 돌더라도 충돌할 위험이 줄어든다.
https://developer.android.com/reference/kotlin/java/lang/Thread?hl=en
Thread | Android Developers
android.net.wifi.hotspot2.omadm
developer.android.com
* 안드로이드 공식 사이트 참고
- 기본과 동기화 (synchronized)
private int tickTime = 60;
private Thread threadTimeTick = null;
private Thread thread = new Thread(new Runnable() {
@Override
public void run() {
synchronized (this){
Log.d("CHECK CURRENT TIME","current time is "+tickTime);
tickTime--;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
private void startThread(){
/**Thread 초기화*/
if(threadTimeTick != null){
threadTimeTick.interrupt();
threadTimeTick = null;
}
/**Thread 실행*/
threadTimeTick = new Thread(thread);
threadTimeTick.start();
try {
threadTimeTick.join();
}catch (Exception e){
e.printStackTrace();
}
Log.d("CHECK THREAD STATE","Thread end");
}
아래의 startThread 메소드를 호출하면 threadTimeTick 쓰레드가 초기화된 후 실행 된다.
start 아래의 threadTimeTick.join()을 사용하면 threadTimeTick와 같은 서브 쓰레드의 종료를 알 수 있으며
종료 체크한 후 동작을 해야하기 때문에 메인 쓰레드에서 자연스럽게 서브 쓰레드의 종료를 기다린다.
유심히 봐야 할 부분은 위의 쓰레드 정의 부분이다.
바깥에서부터 뜯어보자
1. run () : 쓰레드 사용에 필수적인 부분으로 내부에 쓰레드를 실행했을 때 동작할 내용을 작성한다
2. synchronized(this) : 동기화
-> 쓰레드에서 동기화란 하나의 주체가 쓰레드를 이용하는 동안에는 다른 주체가 관여하거나 이용할 수 없도록 기능 한다.
매개변수로 this가 들어간 경우에는 해당 블록 내에서만 동기화를 보장,
다른 변수가 들어간 경우에는 블록 내에서 해당 변수에 대한 동기화를 보장한다.
3. Thread.sleep() : 다른 동작 전후에 쓰레드를 일정 시간 동안 재우는 기능을 한다.
위의 쓰레드를 실행시키면 60초~1초 동안 시간이 1초 간격으로 찍히는 결과가 나타난다.
- Handler를 이용한 Thread 통신
핸들러를 이용하여 쓰레드 통신을 하는 방법은 쉽게 말해 핸들러로 메세지 객체를 전달하여,
핸들러에 연결된 메세지 큐에 적재하는 방식이다.
(handler.post()를 통해 직접 runnable 객체를 전달할 수도 있다.)
여기서 전달 받은 메세지를 꺼내고 메세지에 연결된 핸들러를 연결하는 작업은 루퍼(Looper)가 담당한다.
여기서 루퍼는 안드로이드 내부의 메인 스레드에 이미 작성이 되어있으며 자동 연결 되므로
필요하다면 오버라이딩하여 로직을 작성하면 된다.
private Thread threadTimeTick = null;
private Handler handler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 0 :
Toast.makeText(mContext,"msg.what is 0",Toast.LENGTH_SHORT).show();
break;
}
}
};
private void sendHandleMessage(){
if (handler != null)
{
Message message = new Message();
message.what = 0;
handler.sendMessage(message);
//handler.post(thread);
}
}
private Thread thread = new Thread(new Runnable() {
@Override
public void run() {
synchronized (this){
sendHandleMessage();
}
}
});
private void startThread(){
/**Thread 초기화*/
if(threadTimeTick != null){
threadTimeTick.interrupt();
threadTimeTick = null;
}
/**Thread 실행*/
threadTimeTick = new Thread(thread);
threadTimeTick.start();
try {
threadTimeTick.join();
}catch (Exception e){
e.printStackTrace();
}
Log.d("CHECK THREAD STATE","Thread end");
}
- runOnUiThread
안드로이드 OS 는 UI 자원에 Main Thread와 Sub Thread가 동시 접근하여 충돌이 발생하는 것을 막기 위해
UI 자원 사용은 UI Thread에서만 가능하도록 했다.
그래서 핸들러로 Runnable 객체를 전달하여 UI 쓰레드를 동작시키는 방법도 추가로 작성한다.
쓰레드에서 UI 자원의 동작은 현재 쓰레드가 UI 쓰레드라면 즉시 처리,
UI 쓰레드가 아니라면 UI 쓰레드의 큐에 적재된다.
private Thread threadTimeTick = null;
private Thread thread = new Thread(new Runnable() {
@Override
public void run() {
synchronized (this){
runOnUiThread(new Runnable() {
@Override
public void run() {
textView.setText("runOnUiThread");
}
});
}
}
});
private void startThread(){
/**Thread 초기화*/
if(threadTimeTick != null){
threadTimeTick.interrupt();
threadTimeTick = null;
}
/**Thread 실행*/
threadTimeTick = new Thread(thread);
threadTimeTick.start();
try {
threadTimeTick.join();
}catch (Exception e){
e.printStackTrace();
}
Log.d("CHECK THREAD STATE","Thread end");
}
적재적소에 맞게 쓸 수 있다면 효율성과 메모리 관리에 효과적일 것으로 보인다.
'JAVA > Android' 카테고리의 다른 글
[JAVA][Android] 스택에 2개 이상의 앱이 쌓여 발생한 이슈와 대안, 스택 내용 확인하는 ADB 명령어 (0) | 2022.09.01 |
---|---|
[JAVA][Android] 화면 변경을 감지하는 ViewTreeObserver (0) | 2022.08.31 |
[JAVA][Android] GlideUrl을 통해 Url에 권한 부여하기 (0) | 2022.08.18 |
[JAVA][Android] SpannableStringBuilder로 TextView의 일부에만 스타일 지정하기 (0) | 2022.08.05 |
[JAVA][Android] Bundle로 클래스 객체 전달하기 (0) | 2022.07.26 |