Java에는 우선 순위가 매우 낮고 동일한 프로그램의 다른 스레드가 실행되지 않을 때만 실행되는 특수 스레드인 데몬 스레드가 있습니다.
데몬 스레드는 이러한 특성을 갖고 있기 때문에 일반적으로 프로그램의 일반 스레드(사용자 스레드라고도 함)에 대한 서비스를 제공하는 데 사용됩니다. 일반적으로 무한 루프가 있거나 서비스 요청을 기다리거나 작업을 수행하는 데 사용됩니다. CPU 시간이 언제 할당될지 확실하지 않기 때문에 중요한 작업을 수행할 수 없으며 다른 스레드가 실행되지 않으면 자동으로 종료됩니다. 이러한 스레드 유형의 일반적인 응용 프로그램은 Java 가비지 수집입니다.
이 섹션의 예에서는 두 개의 스레드를 생성합니다. 하나는 큐에 이벤트를 쓰는 일반 스레드이고, 다른 하나는 큐에서 이벤트를 지우고 10초 이상 존재하는 이벤트를 삭제하는 데몬 스레드입니다.
알아요
샘플 프로그램을 구현하려면 아래 단계를 따르세요.
1. 프로그램 실행에 필요한 이벤트 정보를 저장하는 용도로만 사용되는 Event 클래스를 생성합니다. 두 개의 속성을 선언합니다. 하나는 java.util.Date 유형의 날짜 속성이고 다른 하나는 String 유형의 이벤트 속성입니다. 그런 다음 이 두 속성에 대한 읽기 및 쓰기 메서드를 생성합니다. 코드는 다음과 같습니다:
다음과 같이 코드 코드를 복사합니다.
공개 수업 이벤트 {
개인 날짜 날짜;
개인 문자열 이벤트;
공개 날짜 getDate() {
귀국일;
}
public void setDate(날짜 날짜) {
this.date = 날짜;
}
공개 문자열 getEvent() {
복귀 이벤트;
}
공공 무효 setEvent(문자열 이벤트) {
this.event = 이벤트;
}
}
2. WriterTask라는 클래스를 생성하고 Runnable 인터페이스를 구현합니다. 코드는 다음과 같습니다:
다음과 같이 코드 코드를 복사합니다.
공개 클래스 WriterTask는 Runnable을 구현합니다.
3. 이벤트를 저장하는 데 사용되는 대기열 속성을 선언하고, 클래스의 생성자를 구현하고, 해당 매개변수를 사용하여 대기열 속성을 초기화합니다. 코드는 다음과 같습니다:
다음과 같이 코드 코드를 복사합니다.
private Deque<이벤트> deque;
공공 WriterTask(Deque<이벤트> deque) {
this.deque = 데크;
}
4. 100회 순회하는 루프가 포함된 이 작업의 run() 메서드를 구현합니다. 각 순회에서 새 Event 객체가 생성된 다음 대기열에 저장되고 1초 동안 휴면 상태로 유지됩니다. 코드는 다음과 같습니다:
다음과 같이 코드 코드를 복사합니다.
@보수
공개 무효 실행() {
for (int i = 0; i < 100; i++) {
이벤트 이벤트 = new Event();
event.setDate(new Date());
event.setEvent(String.format("%s 스레드가 이벤트를 생성했습니다.",
Thread.currentThread().getId()));
deque.addFirst(이벤트);
노력하다 {
TimeUnit.SECONDS.sleep(1);
} 잡기(InterruptedException e) {
e.printStackTrace();
}
}
}
5. CleanerTask라는 클래스를 생성하고 Thread 클래스를 상속합니다. 코드는 다음과 같습니다:
다음과 같이 코드 코드를 복사합니다.
공개 클래스 CleanerTask는 Thread {를 확장합니다.
6. 이벤트를 저장하는 데 사용되는 대기열 속성을 선언하고, 클래스의 생성자를 구현하고, 해당 매개변수를 사용하여 대기열 속성을 초기화합니다. 생성 메소드에서 setDaemon() 메소드를 호출하여 스레드를 데몬 스레드로 설정합니다. 코드는 다음과 같습니다:
다음과 같이 코드 코드를 복사합니다.
private Deque<이벤트> deque;
공공 CleanerTask(Deque<이벤트> deque) {
this.deque = 데크;
setDaemon(true);
}
7. run() 메소드를 구현하십시오. 메소드 본문에는 현재 시간을 얻은 다음 clearn() 메소드를 호출하는 무한 루프가 있습니다. 코드는 다음과 같습니다:
다음과 같이 코드 코드를 복사합니다.
@보수
공개 무효 실행() {
동안 (참) {
날짜 날짜 = new Date();
청소(날짜);
}
}
8. clean() 메소드를 구현하여 마지막 시간을 가져와서 현재 시간과의 시간 차이를 확인합니다. 10초 전에 생성된 경우 현재 이벤트를 삭제한 후 다음을 확인합니다. 이벤트. 이벤트가 삭제되면 삭제된 이벤트에 대한 정보가 출력되며, 최근 큐 길이도 출력되어 프로그램의 실행 진행 상황을 관찰할 수 있다. 코드는 다음과 같습니다:
다음과 같이 코드 코드를 복사합니다.
private void clean(날짜 날짜) {
긴 차이;
부울 삭제;
if (deque.size() == 0) {
반품;
}
삭제 = 거짓;
하다 {
이벤트 e = deque.getLast();
차이 = date.getTime() - e.getDate().getTime();
if (차이 > 10000) {
System.out.printf("클리너: %s/n", e.getDate());
deque.removeLast();
삭제 = 사실;
}
} while(차이 > 10000);
만약 (삭제) {
System.out.printf("학습자: 대기열 크기: %d/n", deque.size());
}
}
9. 프로그램의 메인 클래스인 Main 클래스를 생성한 다음 main() 메서드를 구현합니다. 코드는 다음과 같습니다:
다음과 같이 코드 코드를 복사합니다.
공개 클래스 메인 {
공개 정적 무효 메인(String[] args) {
10. Deque 클래스를 사용하여 이벤트를 저장할 대기열을 만듭니다. 코드는 다음과 같습니다:
다음과 같이 코드 코드를 복사합니다.
Deque<Event> deque = new ArrayDeque<>();
11. WriterTask 스레드 3개와 CleanerTask 스레드 1개를 생성하고 시작합니다. 코드는 다음과 같습니다:
다음과 같이 코드 코드를 복사합니다.
Deque<Event> deque = new ArrayDeque<>();
WriterTask 작가 = 새로운 WriterTask(deque);
for (int i = 0; i < 3; i++) {
쓰레드 쓰레드 = new Thread(writer);
thread.start();
}
CleanerTask Cleaner = new CleanerTask(deque);
클리너.시작();
12. 프로그램을 실행하고 실행 결과를 확인합니다.
왜인지 알아
프로그램의 실행 결과를 분석해 보면 큐가 처음에는 30으로 증가한 다음 프로그램 실행이 끝날 때까지 27에서 30 사이에서 변경되는 것을 볼 수 있습니다.
프로그램은 먼저 세 개의 WriterTask 스레드에서 실행을 시작합니다. 각 스레드는 먼저 큐에 이벤트를 추가한 다음 1초 동안 휴면합니다. 처음 10초가 지나면 대기열에 30개의 이벤트가 있게 됩니다. 이 10초 동안 세 개의 WriterTask 스레드가 모두 절전 모드로 전환되면 CleanerTask 스레드도 실행되지만 모든 이벤트의 생성 시간이 10초를 초과하지 않으므로 이벤트가 삭제되지 않습니다. 처음 10초 후에는 3개의 WriterTask가 1초마다 3개의 이벤트를 대기열에 추가합니다. 마찬가지로 CleanerTask는 1초마다 3개의 이벤트를 삭제합니다. 따라서 이벤트 수는 27~30개 사이입니다.
WriterTask 스레드가 모두 휴면 상태일 때 우리는 자유롭게 시간을 처리할 수 있으므로 이 시간 동안 데몬 스레드가 실행될 수 있습니다. WriterTask 스레드의 절전 시간을 더 짧게 설정하면 CleanerTask 스레드의 CPU 실행 시간이 줄어듭니다. 이 경우 CleanerTask 스레드가 충분한 이벤트를 삭제할 만큼 충분한 실행 시간을 확보하지 못하기 때문에 대기열의 길이가 계속해서 늘어납니다.
끝나지 않는
스레드는 start() 메서드를 호출하기 전에 setDaemon() 메서드를 호출해야만 데몬 스레드로 설정할 수 있습니다. 스레드가 실행되기 시작하면 데몬 상태를 수정할 수 없습니다.
isDaemon()을 사용하여 스레드가 데몬 스레드인지 확인할 수도 있습니다. 데몬 스레드인 경우 true를 반환하고, 일반 스레드인 경우 false를 반환합니다.
교리를 사용하라
이 글은 "Java 7 Concurrency Cookbook"(D Gua Ge가 "Java7 Concurrency 예제 모음"으로 훔쳤습니다)을 번역한 것이며, 학습 자료로만 사용됩니다. 허가 없이 상업적인 목적으로 사용할 수 없습니다.
작은 성공
이 섹션에 사용된 모든 샘플 코드의 전체 버전입니다.
Event 클래스의 전체 코드
다음과 같이 코드 코드를 복사합니다.
패키지 com.diguage.books.concurrencycookbook.chapter1.recipe7;
java.util.Date 가져오기;
/**
*이벤트 정보 수업
* 날짜: 2013-09-19
* 시간: 22:56
*/
공개 수업 이벤트 {
개인 날짜 날짜;
개인 문자열 이벤트;
공개 날짜 getDate() {
귀국일;
}
public void setDate(날짜 날짜) {
this.date = 날짜;
}
공개 문자열 getEvent() {
복귀 이벤트;
}
공공 무효 setEvent(문자열 이벤트) {
this.event = 이벤트;
}
}
WriterTask 클래스의 전체 코드
다음과 같이 코드 코드를 복사합니다.
패키지 com.diguage.books.concurrencycookbook.chapter1.recipe7;
java.util.Date 가져오기;
import java.util.Deque;
import java.util.concurrent.TimeUnit;
/**
* 매초마다 이벤트를 생성합니다.
* 날짜: 2013-09-19
* 시간: 22:59
*/
공개 클래스 WriterTask는 Runnable을 구현합니다.
private Deque<이벤트> deque;
공공 WriterTask(Deque<이벤트> deque) {
this.deque = 데크;
}
@보수
공개 무효 실행() {
for (int i = 0; i < 100; i++) {
이벤트 이벤트 = new Event();
event.setDate(new Date());
event.setEvent(String.format("%s 스레드가 이벤트를 생성했습니다.",
Thread.currentThread().getId()));
deque.addFirst(이벤트);
노력하다 {
TimeUnit.SECONDS.sleep(1);
} 잡기(InterruptedException e) {
e.printStackTrace();
}
}
}
}
CleanerTask 클래스의 전체 코드
다음과 같이 코드 코드를 복사합니다.
패키지 com.diguage.books.concurrencycookbook.chapter1.recipe7;
java.util.Date 가져오기;
import java.util.Deque;
/**
* 이벤트 정리
* 날짜: 2013-09-19
* 시간: 23:33
*/
공개 클래스 CleanerTask는 Thread {를 확장합니다.
private Deque<이벤트> deque;
공공 CleanerTask(Deque<이벤트> deque) {
this.deque = 데크;
setDaemon(true);
}
@보수
공개 무효 실행() {
동안 (참) {
날짜 날짜 = new Date();
청소(날짜);
}
}
/**
* 이벤트를 삭제합니다.
*
* @param 날짜
*/
private void clean(날짜 날짜) {
긴 차이;
부울 삭제;
if (deque.size() == 0) {
반품;
}
삭제 = 거짓;
하다 {
이벤트 e = deque.getLast();
차이 = date.getTime() - e.getDate().getTime();
if (차이 > 10000) {
System.out.printf("클리너: %s/n", e.getDate());
deque.removeLast();
삭제 = 사실;
}
} while(차이 > 10000);
만약 (삭제) {
System.out.printf("학습자: 대기열 크기: %d/n", deque.size());
}
}
}
Main 클래스의 전체 코드
다음과 같이 코드 코드를 복사합니다.
패키지 com.diguage.books.concurrencycookbook.chapter1.recipe7;
import java.util.ArrayDeque;
import java.util.Deque;
/**
* 날짜: 2013-09-19
* 시간: 23:54
*/
공개 클래스 메인 {
공개 정적 무효 메인(String[] args) {
Deque<Event> deque = new ArrayDeque<>();
WriterTask 작가 = 새로운 WriterTask(deque);
for (int i = 0; i < 3; i++) {
쓰레드 쓰레드 = new Thread(writer);
thread.start();
}
CleanerTask Cleaner = new CleanerTask(deque);
클리너.시작();
}
}