
스레드(Thread) : 프로그램을 차례대로 실행하는 한 개의 흐름 단위
- 싱글스레드 : 한 개의 프로세스 / 프로그램에 한개의 스레드만 사용하는 것
- 멀티스레드 : 한 개의 프로세스 / 프로그램에 여러개의 스레드를 사용하는 것
-> 장점 : 동일한 시간 흐름에 여러가지 명령 및 데이터 처리가 한꺼번에 일어나 동일한 업무를 처리속도가 향상된다.
멀티 스레드 장 / 단점
1) 장점 :
- 응답 / 처리속도가 빨라진다. : 한개의 프로세스에서 처리해야 할 명령이 동시에 시작 및 종료된다.
- 자원 공유의 효율성이 증가한다. : 공유 메모리를 선언해 전역 변수인 static보다 비교적 적은 용량으로 값 공유 가능
- 코드 가시성이 증가한다. : 스레드로 선언 시 스레드 간 어떤 데이터가 교환되는지 / 어떻게 병행하여 실행할지에 대한 코드가 간결해지고 명확해진다.
2) 단점 :
- ★데이터 무결성을 보장하기 위한 극강의 노력이 필요하다.
- 코드 빌딩, 디버깅이 껄끄럽고 복잡시럽다. : 스레드가 동시에 실행되므로 어느 부분에 문제가 있는지 파악이 어렵다.
- 동일한 데이터에 다중의 스레드가 동시에 접근 시 문제 : 병목현상, 값 변경시 데이터의 신뢰성 문제 등 문제 발생
ex ) A 스레드는 공유 메모리 Shared에서 i = 1라는 변수를 2로 변경 시 동시 접근한 B스레드는 1을 꺼낼 텐데..?
-> 이는 java 데이터 동기화(Synchronized) 기능을 통해 해결 가능 / 별도로 Synchronized 포스트에서 다룰 예정
멀티 스레드의 구현
1) 구현 방법 : 클래스 Thread를 상속 (Extends Thread) / 인터페이스 Runnable을 이식(implements Runnable)
- 위의 두 방식은 모두 java5 시절 스레드를 구현하기 위한 옛날 API이어서 실 개발에는 잘 사용되지 않는다.
- 요즘에는 Executor ~ Future, Flow까지 스레드를 구현하는 많은 방법이 있는데, 이는 점차 공부하면서 적어보겠다.
2) Extends Thread를 활용한 구현
- 스레드가 처리할 내용은 상속받은 Thread 클래스 내 메소드인 run()을 오버라이드하여 재정의 및 구현해야한다.
- run() 메서드를 구현 후 호출하기 위해서는 외부에서 스레드 생성 후 run() 메서드가 아닌 start()로 호출해야 한다.
- Thread 클래스가 제공하는 기본 메서드 : run(현재 스레드의 작성된 코드 실행), join(다른 스레드의 작업 대기, 순서 제어), interrupt(다른 스레드가 끼어들게 함), slepp(현재 메서드를 일시 대기시킴)
예시 코드에서 한 개의 프로세스에서 두 개의 스레드가 동일한 시간흐름에서 처리됨을 확인하기 위해
첫 번째 스레드는 Sleep()과 println 메서드를 활용해 일정 시간마다 처리 동작을 측정하였다.
AThread 구현
class AThread extends Thread{ /* 10초 간 1초 단위로 실행 시간을 출력하는 쓰레드 */ public void run() { try { System.out.println("AThread : The World!"); for (int i = 1; i <= 10; i++) { Thread.sleep(1000); /* Thread 클래스 안의 sleep 메소드 */ // 1000ms = 1초간 thread를 정지한다. * 사용에 try / catch 구문 필요 System.out.println("AThread : " + i + "초 경과"); } System.out.println("[!] AThread 실행 완료"); }catch(Exception e){ System.out.println(e); } } }
Thread를 Extends 한 AThread를 만들었다.
AThread.start()를 통해 스레드가 실행되는 시점부터 1초에 한 번씩 sleep()을 하며, for문 종료 시 최종 실행 시점부터 1000ms가 경과한 시점에 스레드 실행 완료라는 println을 출력할 것이다.
BThread 구현
class BThread extends Thread{ /* 0.5초 단위로 알파벳 출력하는 쓰레드 */ public void run() { try { System.out.println("BThread : 알파벳을 셀게요"); for (char alp = 'A'; alp <= 'Z'; alp++) { Thread.sleep(500); /* Thread 클래스 안의 sleep 메소드 */ System.out.println("BThread : " + alp); } System.out.println("[!] BThread 실행 완료"); }catch(Exception e){ System.out.println(e); } } }
Bthread는 500ms 단위로 sleep()을 하며 최종적으로 A부터 Z까지를 println으로 출력하는 스레드를 실행 후 종료된다.
main 구현
public class ThreadTest { public static void main(String[] args) { //실행할 쓰레드 객체 생성 AThread at = new AThread(); BThread bt = new BThread(); // 실행 순서 : at 쓰레드 -> main 메소드 1 -> bt 쓰레드 -> main 메소드 2 at.start(); System.out.println("MainMethod1 : 저는 빠르게 실행됩니다"); System.out.println("[!] MainMethod1 실행 완료"); bt.start(); int sum = 0; for(int i = 0; i <= 100; i++) sum += i; System.out.println("MainMethod2 : 1 ~ 100의 sum : "+sum); System.out.println("[!] MainMethod2 실행 완료"); } }
Athread와 Bthread 객체 생성 후 각자 start() 메서드를 통해 A, B 스레드 내부 run() 메소드를 작동시킨다.
추가적으로 메인 클래스 내부에도 별도 0 ~ 100까지의 합을 구하는 처리 메소드를 구현해 총 3개의 처리 순서를 확인했다.
(A스레드의 메서드, B스레드의 메소드, main 클래스의 처리)
실행 결과
MainMethod1 : 저는 빠르게 실행됩니다 [!] MainMethod1 실행 완료 AThread : The World! BThread : 알파벳을 셀게요 MainMethod2 : 1 ~ 100의 sum : 5050 [!] MainMethod2 실행 완료 BThread : A BThread : B AThread : 1초 경과 BThread : C AThread : 2초 경과 BThread : D BThread : E AThread : 3초 경과 BThread : F BThread : G AThread : 4초 경과 BThread : H BThread : I AThread : 5초 경과 BThread : J BThread : K AThread : 6초 경과 BThread : L BThread : M AThread : 7초 경과 BThread : N BThread : O AThread : 8초 경과 BThread : P BThread : Q AThread : 9초 경과 BThread : R BThread : S AThread : 10초 경과 [!] AThread 실행 완료 BThread : T BThread : U BThread : V BThread : W BThread : X BThread : Y BThread : Z [!] BThread 실행 완료
실행 순서 : 코드에 나와있는 대로 A스레드 → Mainmethod1 → B스레드 → Mainmethod2이지만
비교적 처리가 빠른 main의 두 메서드가 가장 빠르게 처리되고, 이후 A, B스레드가 14000ms 내로 처리되었다.
이와 같이 동시다발적으로 처리가 진행됨을 확인할 수 있다.
예시에서 확인할 수 있듯이
멀티 스레드 개념을 사용하면 일반적인 싱글 프로세스 - 싱글 스레드 보다
프로세스 처리하는 시간을 절감 / 메모리 공간을 효율적으로 활용할 수 있다.
멀티스레드를 활용한 공유 메모리 구현은 다음 포스팅에서 이어진다.
2023.08.17 - [DEV/Java] - [java] 멀티스레드를 활용한 공유 메모리 구현
[java] 멀티스레드를 활용한 공유 메모리 구현
0. 같이 보면 좋을 포스팅"공유 메모리와 멀티 스레드의 이해" 포스팅에서 이어집니다. [java 기초] 공유 메모리와 멀티 스레드의 이해0. 이전 포스팅 : "멀티 스레드의 이해와 구현" 에서 이어지는
doinitright.tistory.com
'DEV > Java' 카테고리의 다른 글
[java] 멀티스레드를 활용한 공유 메모리 구현 (0) | 2023.08.17 |
---|---|
[java] java 메모리 구조와 공유 메모리의 이해 (0) | 2023.08.04 |
[java] java 객체의 직렬화와 역직렬화 (Serialization / Deserialization) (0) | 2023.07.30 |
[java] java 접근 제어자 final, static, private (0) | 2023.07.27 |
[java] 접근 제어자의 이해와 구현 예제(Access Modifier) (0) | 2023.07.26 |