Java 멀티스레드 프로그래밍에서 스레드의 시작, 중단 또는 종료 작업 상세 정보
1.start()와 run()의 차이점 설명
start (): 새 라인을 시작하는 것이 역할입니다. 새 라인은 상응하는run () 방법을 실행합니다.start () 는 중복 호출될 수 없습니다.
run (): run () 은 일반적인 구성원 방법과 마찬가지로 중복 호출될 수 있습니다.run () 을 단독으로 호출하면 현재 라인에서 run () 을 실행하고 새 라인을 시작하지 않습니다!
다음은 코드로 설명합니다.
class MyThread extends Thread{
public void run(){
...
}
};
MyThread mythread = new MyThread();
mythread.start () 는 새 라인을 시작하고 run () 방법을 실행합니다.mythread.run () 은 현재 라인에서 run () 방법을 직접 실행하고, run () 을 실행하기 위해 새 라인을 시작하지 않습니다.
2.start()와 run()의 차이점 예시
다음은 간단한 예시를 통해 그것들 사이의 차이를 보여 준다.소스 코드는 다음과 같습니다.
// Demo.java
class MyThread extends Thread{
public MyThread(String name) {
super(name);
}
public void run(){
System.out.println(Thread.currentThread().getName()+" is running");
}
};
public class Demo {
public static void main(String[] args) {
Thread mythread=new MyThread("mythread");
System.out.println(Thread.currentThread().getName()+" call mythread.run()");
mythread.run();
System.out.println(Thread.currentThread().getName()+" call mythread.start()");
mythread.start();
}
}
실행 결과:
main call mythread.run()
main is running
main call mythread.start()
mythread is running
결과 설명:(1) Thread.currentThread().getName () 은 현재 스레드를 가져오는 데 사용되는 이름입니다.현재 스레드는 cpu에서 실행 중인 스레드를 가리킨다.
(2) mythread.run () 은 "주선main"에서 호출되며, 이 run () 방법은 "주선main"에서 직접 실행됩니다.
(3) mythread.start () 는 "스레드 mythread"를 시작하고, "스레드 mythread"가 시작되면 run () 방법을 호출합니다.이때run () 방법은'선정 mythread'에서 실행됩니다.
스레드의 중단과 종료
1. 스레드 중단:interrupt ()
interrupt () 의 역할은 이 라인을 중단하는 것입니다.
이 라인은 자신이 허락하는 것을 중단한다.다른 스레드가 이 스레드의 interrupt () 방법을 호출할 때 checkAccess () 를 통해 권한을 검사합니다.SecurityException 예외가 발생할 수 있습니다.
이 스레드가 막힌 상태라면: 스레드를 호출하는wait(),wait(long),wait(long,int)는 기다림(막힘) 상태로 들어가게 하거나, 스레드를 호출하는join(),join(long),sleep(long,int)도 막힌 상태로 들어가게 합니다.만약 루틴이 막힌 상태에서 인터럽트 () 방법을 사용한다면,'중단 상태'는 제거되고 인터럽트 exception 이상을 받을 것입니다.예를 들어 라인은wait()를 통해 막힌 상태로 들어가고,interrupt()를 통해 이 라인을 중단합니다.인터럽트 () 를 호출하면 라인의 인터럽트 표시를 "true"로 설정하지만, 라인이 막힌 상태이기 때문에, 이 인터럽트 표시는 "false"로 삭제되며, 인터럽트 exception의 이상이 발생합니다.
만약 라인이 Selector 선택기에 막히면,interrupt () 를 통해 중단할 때;스레드의 인터럽트 표시는true로 설정되고 선택 동작에서 바로 되돌아옵니다.
앞에서 말한 상황에 속하지 않으면,interrupt () 를 통해 라인을 끊을 때, 인터럽트 표시는 "true"로 설정됩니다.
종료된 스레드를 중단하면 작업이 수행되지 않습니다.
2. 스레드 종료
Thread의 stop () 및 suspend () 방법은 고유의 불안정성 때문에 더 이상 사용하지 않는 것을 권장합니다!
다음은 내가 먼저 라인이'막힌 상태'와'운행 상태'의 종료 방식을 각각 토론한 다음에 통용되는 방식을 총결해 보겠다.
1.'막힌 상태'에 있는 라인을 종료합니다
일반적으로 우리는'중단'방식을 통해'막힌 상태'에 있는 라인을 중지한다.
라인이sleep(),wait(),join() 등 방법으로 호출되어 막힌 상태에 들어가면;이 때 루트의interrupt () 를 호출하면 루트의 인터럽트 표시를true로 설정합니다.막힌 상태이기 때문에 인터럽트 표시가 제거되고 인터럽트 Exception 이상이 발생합니다.Interrupted Exception을 적절한 위치에 두면 다음 형식으로 스레드를 종료할 수 있습니다.
@Override
public void run() {
try {
while (true) {
// ...
}
} catch (InterruptedException ie) {
// InterruptedException , while(true) , !
}
}
설명:while (true) 에서 끊임없이 작업을 수행합니다. 루틴이 막힌 상태일 때, 루틴을 호출하는interrupt () 는 InterruptedException 중단을 발생합니다.중단된 포획은while (true) 이외에,while (true) 순환에서 종료됩니다!주의:Interrupted Exception에 대한 포획 업무는 일반적으로while (true) 순환체 밖에 놓여 있으며, 이상이 발생하면while (true) 순환에서 물러납니다.그렇지 않으면,InterruptedException은while (true) 순환체 안에 있으며, 종료 처리를 추가로 추가해야 합니다.형식은 다음과 같습니다.
@Override
public void run() {
while (true) {
try {
// ...
} catch (InterruptedException ie) {
// InterruptedException while(true) 。
// InterruptedException ,while(true) !
break;
}
}
}
설명: 위의 Interrupted Exception 예외는 whle(true) 안에 있습니다.Interrupted Exception 이상이 발생했을 때catch 처리 외에도while(true) 순환 체내에 있습니다.while (true) 순환체를 종료하려면 while (true) 를 종료하는 작업을 추가로 수행해야 합니다.2. 실행 중인 스레드를 종료합니다.
일반적으로, 우리는'표시'방식을 통해'실행 상태'에 있는 라인을 끝냅니다.여기에는 브레이크 태그 및 추가 태그가 포함됩니다.
(1) 인터럽트 태그를 통해 스레드를 종료합니다.
형식은 다음과 같습니다.
@Override
public void run() {
while (!isInterrupted()) {
// ...
}
}
설명: isInterrupted () 는 스레드의 중단 표시가true인지 아닌지를 판단합니다.라인이 운행 상태에 있고 우리가 그것을 중지해야 할 때;스레드의 인터럽트 () 방법을 호출할 수 있습니다. 스레드의 인터럽트 표시를true로 표시하면 isInterrupted () 가true로 되돌아옵니다.while 순환이 종료됩니다.주의:interrupt () 는 "운행 상태"의 라인을 종료하지 않습니다!이것은 라인의 인터럽트 표시를true로 설정합니다.
(2) 태그 추가를 통해
형식은 다음과 같습니다.
private volatile boolean flag= true;
protected void stopTask() {
flag = false;
}
@Override
public void run() {
while (flag) {
// ...
}
}
설명: 라인에 flag 표시가 있습니다. 기본값은true입니다.또한 flag 태그를 설정하기 위해 stopTask () 를 제공합니다.이 라인을 종료해야 할 때, 이 라인의stopTask () 방법을 사용하면 while 순환을 종료할 수 있습니다.주의: 플래그를volatile 형식으로 정의하는 것은 플래그의 가시성을 확보하기 위해서입니다.즉, 다른 스레드가 stopTask () 를 통해 flag를 수정한 후, 이 스레드는 수정된 flag의 값을 볼 수 있습니다.
종합 스레드는 "막힘 상태"와 "운행 상태"의 종료 방식에 있으며, 비교적 통용되는 종료 스레드의 형식은 다음과 같다.
@Override
public void run() {
try {
// 1. isInterrupted() , true 。
while (!isInterrupted()) {
// ...
}
} catch (InterruptedException ie) {
// 2. InterruptedException , InterruptedException , 。
}
}
3. 종료 스레드의 예인터럽트 () 는 종종'막힌 상태'라인을 종료하는 데 사용됩니다.다음 예제를 참조하십시오.
// Demo1.java
class MyThread extends Thread {
public MyThread(String name) {
super(name);
}
@Override
public void run() {
try {
int i=0;
while (!isInterrupted()) {
Thread.sleep(100); // 100ms
i++;
System.out.println(Thread.currentThread().getName()+" ("+this.getState()+") loop " + i);
}
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() +" ("+this.getState()+") catch InterruptedException.");
}
}
}
public class Demo1 {
public static void main(String[] args) {
try {
Thread t1 = new MyThread("t1"); // “ t1”
System.out.println(t1.getName() +" ("+t1.getState()+") is new.");
t1.start(); // “ t1”
System.out.println(t1.getName() +" ("+t1.getState()+") is started.");
// 300ms, t1 “ ” 。
Thread.sleep(300);
t1.interrupt();
System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");
// 300ms, t1 。
Thread.sleep(300);
System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
실행 결과:
t1 (NEW) is new.
t1 (RUNNABLE) is started.
t1 (RUNNABLE) loop 1
t1 (RUNNABLE) loop 2
t1 (TIMED_WAITING) is interrupted.
t1 (RUNNABLE) catch InterruptedException.
t1 (TERMINATED) is interrupted now.
결과 설명:(1) 주 스레드 main에서 new MyThread("t1")를 통해 스레드 t1을 만들고 t1을 통해.start () 시작 스레드 t1.
(2)t1이 시작되면 중단 표시를 끊임없이 검사합니다. 중단 표시가'false'라면.수면 100ms.
(3)t1이 휴면하면 메인 라인main으로 전환됩니다.주 스레드가 다시 실행될 때 t1을 실행합니다.interrupt () 인터럽트 루트 t1.t1이 인터럽트 명령을 받으면 t1의 인터럽트 태그를 "false"로 설정하고 인터럽트 exception 이상을 던집니다.t1의run() 방법에서 순환체while 밖에서 포착된 이상입니다.따라서 순환이 중지됩니다.
우리는 위의 결과를 작은 수정하여run () 방법에서 Interrupted Exception 이상을 포획한 코드 블록을while 순환 체내로 옮깁니다.
// Demo2.java
class MyThread extends Thread {
public MyThread(String name) {
super(name);
}
@Override
public void run() {
int i=0;
while (!isInterrupted()) {
try {
Thread.sleep(100); // 100ms
} catch (InterruptedException ie) {
System.out.println(Thread.currentThread().getName() +" ("+this.getState()+") catch InterruptedException.");
}
i++;
System.out.println(Thread.currentThread().getName()+" ("+this.getState()+") loop " + i);
}
}
}
public class Demo2 {
public static void main(String[] args) {
try {
Thread t1 = new MyThread("t1"); // “ t1”
System.out.println(t1.getName() +" ("+t1.getState()+") is new.");
t1.start(); // “ t1”
System.out.println(t1.getName() +" ("+t1.getState()+") is started.");
// 300ms, t1 “ ” 。
Thread.sleep(300);
t1.interrupt();
System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");
// 300ms, t1 。
Thread.sleep(300);
System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
실행 결과:
t1 (NEW) is new.
t1 (RUNNABLE) is started.
t1 (RUNNABLE) loop 1
t1 (RUNNABLE) loop 2
t1 (TIMED_WAITING) is interrupted.
t1 (RUNNABLE) catch InterruptedException.
t1 (RUNNABLE) loop 3
t1 (RUNNABLE) loop 4
t1 (RUNNABLE) loop 5
t1 (TIMED_WAITING) is interrupted now.
t1 (RUNNABLE) loop 6
t1 (RUNNABLE) loop 7
t1 (RUNNABLE) loop 8
t1 (RUNNABLE) loop 9
...
결과 설명:프로그램이 사순환에 들어갔습니다!
왜 이러지?이것은 t1이'대기(막힘)상태'에서 인터럽트 () 에 의해 중단되었기 때문이다.이 때 인터럽트 표시 [즉 isInterrupted () 는false] 로 되돌아오고 인터럽트 Exception 이상을 던집니다. [이 이상은while 순환체 내에서 포착됩니다.]따라서 t1은 당연히 사순환에 들어갈 것이다.
이 문제를 해결하려면 이상을 포착할 때 while 순환을 종료하는 추가 처리가 필요합니다.예를 들어 MyThread의catch(Interrupted Exception)에 브레이크나 리턴을 추가하면 이 문제를 해결할 수 있습니다.
다음은 "태그 추가"방식으로 "상태 상태"라인을 종료하는 예입니다.
// Demo3.java
class MyThread extends Thread {
private volatile boolean flag= true;
public void stopTask() {
flag = false;
}
public MyThread(String name) {
super(name);
}
@Override
public void run() {
synchronized(this) {
try {
int i=0;
while (flag) {
Thread.sleep(100); // 100ms
i++;
System.out.println(Thread.currentThread().getName()+" ("+this.getState()+") loop " + i);
}
} catch (InterruptedException ie) {
System.out.println(Thread.currentThread().getName() +" ("+this.getState()+") catch InterruptedException.");
}
}
}
}
public class Demo3 {
public static void main(String[] args) {
try {
MyThread t1 = new MyThread("t1"); // “ t1”
System.out.println(t1.getName() +" ("+t1.getState()+") is new.");
t1.start(); // “ t1”
System.out.println(t1.getName() +" ("+t1.getState()+") is started.");
// 300ms, t1 “ ” 。
Thread.sleep(300);
t1.stopTask();
System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");
// 300ms, t1 。
Thread.sleep(300);
System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
실행 결과:
t1 (NEW) is new.
t1 (RUNNABLE) is started.
t1 (RUNNABLE) loop 1
t1 (RUNNABLE) loop 2
t1 (TIMED_WAITING) is interrupted.
t1 (RUNNABLE) loop 3
t1 (TERMINATED) is interrupted now.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.