본문 바로가기
Java

[Java] 데이터를 Thread에서 공통으로 사용하는 방법 예제

by teamnova 2023. 10. 17.

안녕하세요 이번 포스팅에서는 오늘은 자바를 사용하여 두 개의 쓰레드가 공통 데이터를 어떻게 공유하는지 보여주는 예제를 함께 살펴보려고 합니다. 이 예제의 목표는 1부터 1,500,000,000까지의 합계를 계산하는 쓰레드와, 그 결과를 출력하는 쓰레드가 어떻게 동작하고 상호 작용하는지 이해하는 것입니다.

 

먼저, 쓰레드는 독립적인 실행 흐름을 가진 프로그램의 한 부분입니다. 여러 쓰레드가 동시에 동작하면서 효율적으로 자원을 사용할 수 있습니다. 하지만, 이렇게 병렬 처리를 할 때 여러 쓰레드가 동일한 메모리나 데이터를 동시에 접근하면 문제가 발생할 수 있습니다. 이 문제를 해결하기 위한 방법 중 하나로 데이터를 안전하게 공유하는 방식을 사용할 것입니다.

 

이 예제에는 크게 세 개의 클래스가 있습니다.  이 클래스들이 어떻게 서로 상호 작용하는지 함께 살펴보겠습니다

 

  • ThreadDataSharingDemo: 메인 실행 클래스로, 여기서 쓰레드들을 시작합니다.
  • SharedResource: 여러 쓰레드에 의해 공유되는 데이터를 관리하는 클래스입니다.
  • SumCalculator: 합계를 계산하는 쓰레드입니다.
  • SumPrinter: 계산된 합계를 출력하는 쓰레드입니다.

주목해야 할 중요한 부분 중 하나는 SharedResource 클래스 내의 isCompleted 변수 앞에 있는 volatile 키워드입니다. 이 키워드는 다중 쓰레드 환경에서 해당 변수의 메모리 가시성을 보장해 줍니다. 즉, 한 쓰레드가 변수 값을 변경하면 다른 쓰레드도 즉시 이 변경을 인지할 수 있게 해줍니다.

 

전체 코드입니다.

public class ThreadDataSharingDemo {
public static void main(String[] args) {
SharedResource resource = new SharedResource();
//SharedResource 객체를 생성하여 공유 데이터를 저장할 인스턴스를 준비합니다.

SumCalculator calculator = new SumCalculator(resource);
SumPrinter printer = new SumPrinter(resource);
//두 개의 쓰레드 객체를 생성합니다. 하나는 합계를 계산(SumCalculator)하고 다른 하나는 계산된 합계를 출력(SumPrinter)합니다.
//두 쓰레드는 동일한 SharedResource 인스턴스를 사용합니다.

calculator.start();
printer.start();
//두 쓰레드를 시작합니다. 각각의 쓰레드는 독립적으로 실행되며, 병렬로 작업을 처리합니다.
}
}

class SharedResource {
//공유할 데이터를 저장하는 SharedResource 클래스를 정의합니다.
public long sumValue;
//계산된 합계 값을 저장하는 변수를 정의합니다.
volatile public boolean isCalculated = false;
//volatile 키워드는 여러 쓰레드에서 변수의 동기화 문제 없이 접근할 수 있게 합니다. isCalculated 변수는 합계 계산이 완료되었는지 여부를 나타냅니다.
}

class SumCalculator extends Thread {
//합계를 계산하는 쓰레드 클래스 SumCalculator를 정의합니다. 이 클래스는 Thread 클래스를 상속받습니다.
private SharedResource resource;
//공유 데이터를 참조하는 SharedResource 객체를 저장하는 멤버 변수를 정의합니다.
public SumCalculator(SharedResource resource) {
this.resource = resource;
//생성자에서 SharedResource 객체를 받아 멤버 변수에 저장합니다.
}

@Override
public void run() {
long total = 0;
long maxNum = 1500000000L;
//합계를 저장할 변수와 최대 숫자 값을 정의합니다.

for(long i = 1; i <= maxNum; i++) {
total += i;
}
resource.sumValue = total;
resource.isCalculated = true;
//계산된 합계를 SharedResource 객체의 변수에 저장하고 계산 완료 상태를 true로 설정합니다.
}
}

class SumPrinter extends Thread {
//계산된 합계를 출력하는 쓰레드 클래스 SumPrinter를 정의합니다.
private SharedResource resource;
//공유 데이터를 참조하는 SharedResource 객체를 저장하는 멤버 변수를 정의합니다.
public SumPrinter(SharedResource resource) {
this.resource = resource;
}

@Override
public void run() {
while (true) {
if (resource.isCalculated) {
break;
}
}
//합계 계산이 완료될 때까지 대기합니다.
System.out.println();
System.out.println("Calculated Sum: " + resource.sumValue);
}

 

시연 영상입니다.