JavaRush /Java Blog /Random-KO /커피 브레이크 #112. Java에서 배열을 선언하고, 초기화하고, 반복하는 방법입니다. Thread....

커피 브레이크 #112. Java에서 배열을 선언하고, 초기화하고, 반복하는 방법입니다. Thread.stop()을 사용하지 않고 Java 스레드를 중지하는 방법은 무엇입니까?

Random-KO 그룹에 게시되었습니다

Java에서 배열을 선언, 초기화 및 반복하는 방법

출처: FreeCodeCamp 이 기사에서는 Java의 배열에 대해 설명합니다. 배열이 무엇인지, 배열을 선언하는 방법, Java 코드에서 배열을 사용하는 방법을 이해하는 데 도움이 되는 몇 가지 예를 살펴보겠습니다. 커피 브레이크 #112.  Java에서 배열을 선언하고, 초기화하고, 반복하는 방법입니다.  Thread.stop()을 사용하지 않고 Java 스레드를 중지하는 방법은 무엇입니까?  - 1

배열이란 무엇입니까?

Java에서는 배열을 사용하여 동일한 데이터 유형의 여러 값을 단일 변수에 저장합니다. 동일한 데이터 유형의 값들의 집합이라고 생각할 수도 있습니다. 이는 예를 들어 배열에 문자열을 저장하려는 경우 배열의 모든 값이 문자열이어야 함을 의미합니다.

Java에서 배열을 선언하는 방법

배열을 선언하려면 대괄호 [] 를 사용합니다 . 그렇게:
String[] names;
여기서는 문자열 배열을 보유할 names 라는 변수를 선언했습니다 . 정수 (정수) 에 대한 변수를 선언해야 하는 경우 다음과 같이 수행합니다.
int[] myIntegers;
따라서 배열을 만들려면 배열에 저장될 데이터 유형을 지정하고 그 뒤에 대괄호와 배열 이름을 지정합니다.

Java에서 배열을 초기화하는 방법

배열을 초기화한다는 것은 배열에 값을 할당하는 것을 의미합니다. 이전 섹션에서 선언한 배열을 초기화해 보겠습니다.
String[] names = {"John", "Jade", "Love", "Allen"};
int[] myIntegers = {10, 11, 12};
동일한 데이터 유형의 값을 전달하고 각 값을 쉼표로 구분하여 배열을 초기화했습니다. 배열의 요소/값에 액세스하려면 배열의 인덱스 번호에 액세스합니다. 첫 번째 요소의 인덱스는 0입니다. 예는 다음과 같습니다.
String[] names = {"John", "Jade", "Love", "Allen"};

System.out.println(names[0]);
// John

System.out.println(names[1]);
// Jade

System.out.println(names[2]);
// Love

System.out.println(names[3]);
// Allen
이제 각 요소에 액세스하는 방법을 알았으므로 세 번째 요소의 값을 변경해 보겠습니다.
String[] names = {"John", "Jade", "Love", "Allen"};
names[2] = "Victor";

System.out.println(names[2]);
// Victor
length 속성을 사용하여 배열의 길이를 확인할 수도 있습니다 . 예는 다음과 같습니다.
String[] names = {"John", "Jade", "Love", "Allen"};
System.out.println(names.length);
// 4

Java에서 배열을 반복하는 방법

for 루프를 사용하여 배열 요소를 반복할 수 있습니다 .
String[] names = {"John", "Jade", "Love", "Allen"};
for (int i = 0; i < names.length; i++) {
  System.out.println(names[i]);
}

// John
// Jade
// Love
// Allen
위의 루프는 배열의 요소를 인쇄합니다. 루프가 실행되어야 하는 횟수를 지정하기 위해 길이 속성을 사용했습니다 .

결론

이번 글에서는 자바 코드에서 배열을 선언하고 초기화하는 방법을 배웠습니다. 또한 배열의 각 요소에 액세스하는 방법과 해당 요소를 반복하는 방법도 살펴보았습니다. 즐거운 코딩하세요!

Thread.stop()을 사용하지 않고 Java 스레드를 중지하는 방법은 무엇입니까?

출처: 4comprehension 이 글을 읽고 있다면 아마도 왜, 그리고 가장 중요하게는 Java 1.2부터 더 이상 사용되지 않는 Thread#stop() 메소드 에 의존할 수 없는 경우 스레드를 중지하는 방법이 궁금할 것입니다. ? 짧은 대답은 Thread#stop이커피 브레이크 #112.  Java에서 배열을 선언하고, 초기화하고, 반복하는 방법입니다.  Thread.stop()을 사용하지 않고 Java 스레드를 중지하는 방법은 무엇입니까?  - 2 안전하지 않기 때문에 중단을 사용해야 한다는 것입니다 . 그러나 성가신 InterruptedException이 왜, 어떻게, 무엇을 위한 것인지 이해하고 싶다면 계속 읽으십시오.

Thread#stop() 문제

아무리 직관적으로 들리더라도 이미 실행 중인 스레드를 중단하는 것, 시작 및 중지는 완전히 다른 두 가지 경우입니다. 왜? 새로운 스레드를 시작하면 처음부터 다시 시작하게 되는데, 이는 잘 정의된 상태이지만, 기존 스레드를 중지하려고 하면 즉시 중단할 수 없는 작업 도중에 발생할 수 있습니다 . 스레드로부터 안전한 데이터 구조를 변경하는 스레드를 상상해 보십시오. 임계 영역의 중간에 있는 동안... 스레드가 마술처럼 사라집니다. 잠금이 해제되고 이제 다른 스레드가 일관되지 않은 상태로 남아 있는 데이터 구조를 관찰할 수 있습니다. 내부 상태가 있는 스레드로부터 안전한 카운터에 대한 다음 예를 살펴보세요.
class ThreadSafeCounter {

    private volatile int counter = 0;
    private volatile boolean dirty = false;

    public synchronized int incrementAndGet() {
        if (dirty) {
            throw new IllegalStateException("this should never happen");
        }
        dirty = true;
        // ...
        Thread.sleep(5000); // boilerplate not included
        // ...
        counter = counter + 1;
        dirty = false;
        return counter;
    }
}
보시다시피, getAndIncrement() 메소드는 카운터를 증가시키고 더티 플래그를 변경합니다 . 잠금은 스레드가 getAndIncrement() 에 들어갈 때마다 더티 플래그가 false 로 설정되도록 보장합니다 . 이제 스레드를 생성하고 이를 갑자기 중지해 보겠습니다.
var threadSafeCounter = new ThreadSafeCounter();

var t1 = new Thread(() -> {
    while (true) {
        threadSafeCounter.incrementAndGet();
    }
});

t1.start();
Thread.sleep(500);
t1.stop();

threadSafeCounter.incrementAndGet();

// Exception in thread "main" java.lang.IllegalStateException: this should never happen
이제 threadSafeCounter 인스턴스 는 올바르게 구현되었음에도 불구하고 스레드가 갑자기 중지되어 영구적으로 손상되었습니다. 어떻게 고치나요?

협동 스레드 중단

스레드를 중지하는 대신 협력적인 스레드 중단을 사용해야 합니다. 간단히 말해서 Thread#interrupt 를 사용하여 적절한 순간에 스레드가 스스로 중지하도록 요청해야 합니다 . 그러나 Thread#stop 대신 Thread#interrupt를 호출하는 것만으로 는 충분하지 않습니다. 스레드의 안전한 종료는 공유 스레드 인터럽트를 통해서만 달성할 수 있습니다. 즉, 스레드 내에서 두 가지 유형의 인터럽트 신호를 처리해야 함을 의미합니다.
  • 부울 중단 플래그

  • 중단된 예외

인터럽트 가능한 플래그 처리

스레드 내부에서 다음 메소드 중 하나를 호출하여 스레드가 중단되었는지 확인할 수 있습니다.
Thread.currentThread().isInterrupted(); // reads the interrupted flag
Thread.interrupted(); // reads and resets the interrupted flag
인터럽트를 처리하는 보편적인 방법이 없기 때문에 상황에 맞는 작업을 적용해야 합니다. 이전 섹션의 예에서 스레드는 무한 루프에서 카운터를 증가시킵니다. 즉시 중지하는 대신 스레드가 오름차순 작업을 완료할 때까지 기다린 다음 루프를 종료할 수 있습니다.
var threadSafeCounter = new ThreadSafeCounter();

var t1 = new Thread(() -> {
    while (!Thread.interrupted()) {
        threadSafeCounter.incrementAndGet();
    }
});

t1.start();
Thread.sleep(500);
t1.interrupt();

threadSafeCounter.incrementAndGet();
이제 스레드는 혼란을 일으키지 않고 적절한 시간에 안전하게 종료됩니다.

InterruptedException 처리

대기 중인 스레드를 중단하려고 하면 어떻게 되나요? 당연히 스레드가 차단 작업으로 바쁘기 때문에 중단 플래그를 고려할 수 없습니다 . 이것이 바로 InterruptedException이 존재하는 이유입니다 . 이는 표준 예외가 아니라 차단 인터럽트를 처리하기 위해 존재하는 다른 형태의 인터럽트 신호입니다! Thread#interrupted 와 마찬가지로 중단 플래그를 재설정합니다 . 위의 예를 다시 변경하고 각 증분 전에 일시 중지를 도입해 보겠습니다. 이제 Thread#sleep 에서 발생한 InterruptedException을 처리해야 합니다 .
var threadSafeCounter = new ThreadSafeCounter();

var t1 = new Thread(() -> {
    while (!Thread.interrupted()) {
        threadSafeCounter.incrementAndGet();
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            break;
        }
    }
});

t1.start();
Thread.sleep(500);
t1.interrupt();

assertThat(threadSafeCounter.incrementAndGet()).isGreaterThan(0);
우리의 경우에는 단순히 루프를 종료하는 것만으로도 충분했습니다. 하지만 특정 메서드가 인터럽트 처리를 담당해야 한다고 생각하지 않는다면 어떻게 될까요? 메소드 서명을 변경할 수 없으면 어떻게 되나요? 이 경우 중단 플래그를 복원 하거나 예외를 다시 패키지 해야 합니다 . 예를 들면 다음과 같습니다.
try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
}
try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
    throw new RuntimeException(e);
}

결론:

  • Thread#stop은 아무런 이유 없이 더 이상 사용되지 않습니다. 실제로는 매우 안전하지 않습니다.

  • 스레드는 중단(스레드 자체에서 해석되는 신호)을 통해 중지됩니다.

  • InterruptedException 은 일반적인 예외가 아닙니다. 이는 스레드가 중단되었음을 알리는 Java의 기본 제공 방식입니다.

  • Thread.currentThread().isInterrupted()Thread.interrupted() 는 같은 것이 아닙니다. 첫 번째는 단순히 중단 플래그를 읽고 , 다른 하나는 나중에 이를 재설정합니다.

  • 인터럽트 신호를 처리하는 보편적인 방법은 없습니다. "상황에 따라 다릅니다."

코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION