Java에서 동시 목록 만들기
동시성은 프로그램이나 기능을 병렬로 실행하는 프로세스입니다. 여러 스레드가 동일한 방법으로 작동하면 시간이 단축되고 처리량이 증가합니다.
Java는 List
작업의 효율적인 방법을 허용하는 CopyOnWriteArrayList
클래스를 제공하며 함수는 스레드로부터 안전한 방식으로 작동합니다. 이는 둘 이상의 스레드가 목록을 조작하려고 할 때 지정된 클래스가 스레드로부터 안전한 방식으로 읽기-쓰기
작업을 허용한다는 것을 의미합니다. 내부적으로 add
또는 remove
기능과 같은 목록 인터페이스의 메서드를 수정할 때 CopyOnWriteArrayList
의 내용은 새 내부 복사본에 복사됩니다. 이 기능을 사용하면 스레드로부터 안전하고 병렬 처리가 가능합니다.
CopyOnWriteArrayList
클래스는 java.util.concurrent
패키지에 있습니다. 다음은 주어진 클래스에 대한 작업을 보여주는 코드 블록 예제입니다.
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class ConcurrentListOperations {
public static void main(String[] args) {
List<Integer> temp_list = Arrays.asList(1, 2, 3);
List<Integer> list = new CopyOnWriteArrayList<>(temp_list);
new WriteThread("Writer", list).start();
new ReadThread("Reader", list).start();
}
}
class WriteThread extends Thread {
private final List<Integer> list;
public WriteThread(String name, List<Integer> list) {
this.list = list;
super.setName(name);
}
public void run() {
int count = 4;
int counter = 0;
do {
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
list.add(count++);
System.out.println(super.getName() + " done");
counter++;
} while (counter != 5);
}
}
class ReadThread extends Thread {
private final List<Integer> list;
public ReadThread(String name, List<Integer> list) {
this.list = list;
super.setName(name);
}
public void run() {
while (true) {
StringBuilder output = new StringBuilder("\n" + super.getName() + ":");
for (Integer nextVal : list) {
output.append(" ").append(nextVal);
}
System.out.println(output);
}
}
}
Java의 드라이버 클래스
위의 프로그램에서는 세 개의 클래스가 정의되어 있습니다. main
메소드가 있는 첫 번째 클래스는 드라이버 클래스이고 나머지는 작동을 위해 존재합니다. ConcurrentListOperations
클래스에서 임시 목록은 처음에 3개의 정수로 초기화됩니다. 형성된 temp_list
는 ArrayList
클래스의 또 다른 유형인 CopyOnWriteArrayList
생성자로 전달됩니다.
클래스는 위에 정의된 값으로 배열을 초기화합니다. 이제 copyOnWriteArrayList
의 인스턴스는 이전에 생성된 스레드 클래스로 전달됩니다. 이 클래스는 목록을 스레드로부터 안전하게 만들기만 합니다. 따라서 목록 인스턴스에서 병렬 작업을 허용합니다.
Java의 스레드 클래스
두 스레드 클래스는 ReadThread
및 WriteThread
입니다. 클래스의 실제 작업은 동일한 목록을 동시에 읽고 쓰는 것입니다. WriteThread
클래스는 스레드를 선언하는 한 가지 방법인 Thread
클래스를 확장합니다. 수신한 목록 인스턴스를 지역 변수에 할당하고 스레드 이름을 초기화하는 공용 생성자가 있습니다.
스레드에 대한 실제 비즈니스 로직은 run
메소드에 있습니다. 스레드를 시작하기 위해 start
메소드는 새로 생성된 스레드 클래스 인스턴스에 대해 호출됩니다.
Java에서 run
메소드 사용
WriteThread
클래스의 run
메서드에서 카운터는 run
메서드에서 write
클래스의 반복을 추적하기 위해 루프 조건에서 초기화됩니다. do-while
루프는 반복 실행 횟수를 추적하는 데 사용됩니다.
조건부 블록 내에서 Thread
클래스의 sleep
메서드가 호출되어 스레드가 정의된 시간 동안 절전 모드로 전환됩니다. 이 함수는 병렬을 실행하여 스레드를 일정한 밀리초 동안 휴면 상태로 만듭니다. 전달된 밀리초가 음수이면 IllegalArgumentException
이 발생하고 스레드가 중단되면 InterruptedException
이 발생합니다.
add
메소드는 동시 스레드에 의해 목록에 요소를 추가하는 데 사용됩니다. 목록 인스턴스에서 작업을 허용하지 않으면 UnsupportedOperationException
이 발생합니다. 반면에 지정된 요소의 클래스가 목록의 동일한 유형이 아닌 경우 ClassCastException
이 발생합니다. 지정된 값이 null이면 NullPointerException
이 발생하고 이 요소의 일부 속성이 요소 추가를 방지하는 경우 IllegalArgumentException
이 발생합니다.
유사하게 ReadThread
클래스의 run
메소드에서 생성자가 정의됩니다. 이름과 목록을 초기화합니다. run
메소드에는 실제 read
로직이 있습니다. StringBuilder
클래스는 출력을 조작하는 데 사용됩니다. append
메소드는 쓰기 스레드 클래스에서 찾은 출력을 기존 출력과 함께 추가합니다.
따라서 읽기
및 쓰기
작업이 동시에 발생하고 위의 형식으로 콘솔에 인쇄됩니다. 쓰기 스레드는 약 5000밀리초 동안 휴면하며 작성기 출력은 읽기
스레드에 비해 표시되는 횟수가 적습니다. ...
는 스레드가 끝없이 실행되고 쓰기
작업이 수행되지 않았기 때문에 동일한 출력을 인쇄함을 나타냅니다. write
프로세스가 성공하면 read
스레드는 이제 새로 추가된 값을 인쇄합니다.
출력:
Reader: 1 2 3
..
Writer done
Reader: 1 2 3 4
...
Writer done
Reader: 1 2 3 4 5
Rashmi is a professional Software Developer with hands on over varied tech stack. She has been working on Java, Springboot, Microservices, Typescript, MySQL, Graphql and more. She loves to spread knowledge via her writings. She is keen taking up new things and adopt in her career.
LinkedIn