java.lang.Thread
Java에서를 어떻게 죽 입니까?
ExecutorStatus
이 질문에 대한 답변을 선호합니다 : stackoverflow.com/questions/2275443/how-to-timeout-a-thread
java.lang.Thread
Java에서를 어떻게 죽 입니까?
ExecutorStatus
이 질문에 대한 답변을 선호합니다 : stackoverflow.com/questions/2275443/how-to-timeout-a-thread
답변:
더 이상 사용되지 않는 이유는 SunThread.stop()
의이 스레드를 참조하십시오 . 왜 이것이 나쁜 방법인지, 그리고 일반적으로 스레드를 안전하게 중지하기 위해 수행해야 할 사항에 대해 자세히 설명합니다.
그들이 권장하는 방법은 공유 변수를 플래그로 사용하여 백그라운드 스레드를 중지하도록 요청하는 것입니다. 그런 다음 스레드 종료를 요청하는 다른 객체로이 변수를 설정할 수 있습니다.
getConnection()
을java.sql.DriverManager
합니다. 연결 시도가 너무 오래 걸리면 호출하여 해당 스레드를 종료하려고 시도 Thread.interrupt()
하지만 스레드에 전혀 영향을 미치지 않습니다. 는 Thread.stop()
오라클이 경우 작동하지한다고 말했습니다 있지만, 그러나 작동 interrupt()
하지 않습니다. 어떻게 작동하는지 궁금하고 더 이상 사용되지 않는 방법을 사용하지 마십시오.
일반적으로 ..
Thread.interrupt ()를 사용하여 수행중인 작업을 중단하도록 요청합니다 (javadoc link)
왜 javadoc에 있는지에 대한 좋은 설명 (java technote link)
Java 스레드에서는 종료되지 않지만 스레드 중지는 협업 방식으로 수행됩니다 . 스레드를 종료하라는 요청을 받으면 스레드가 정상적으로 종료 될 수 있습니다.
volatile boolean
스레드가 해당 값으로 설정 될 때 스레드가 주기적으로 확인하고 종료 하는 필드가 종종 사용됩니다.
나는 하지 않을 를 사용하는 boolean
스레드가해야하는지 여부를 확인하기 위해 종료 . volatile
필드 수정 자로 사용하면 안정적으로 작동하지만 코드가 더 복잡해지면 while
루프 내에서 다른 차단 방법을 사용 하기 때문에 코드가 전혀 종료되지 않거나 적어도 시간이 오래 걸릴 수 있습니다 아마도 원한다.
특정 차단 라이브러리 방법은 중단을 지원합니다.
모든 스레드에는 이미 부울 플래그 중단 상태 가 있으므로 이를 사용해야합니다. 다음과 같이 구현할 수 있습니다.
public void run() {
try {
while (!interrupted()) {
// ...
}
} catch (InterruptedException consumed)
/* Allow thread to exit */
}
}
public void cancel() { interrupt(); }
실제로 Java Concurrency에서 채택한 소스 코드 . cancel()
메소드가 공용 이므로 다른 스레드가 원하는대로이 메소드를 호출 할 수 있습니다.
한 가지 방법은 클래스 변수를 설정하고이를 센티넬로 사용하는 것입니다.
Class Outer {
public static volatile flag = true;
Outer() {
new Test().start();
}
class Test extends Thread {
public void run() {
while (Outer.flag) {
//do stuff here
}
}
}
}
위의 예제에서 외부 클래스 변수, 즉 flag = true를 설정하십시오. 스레드를 'kill'하려면 false로 설정하십시오.
volatile
어디에서나 제대로 작동 하도록 "플래그" 를 만듭니다 . 내부 클래스는 정적이 아니므로 플래그는 인스턴스 변수 여야합니다. 액세서 메소드에서 플래그를 지워서 다른 조작 (예 : 인터럽트)을 수행 할 수 있습니다. "플래그"라는 이름은 설명이 아닙니다.
당신이 그것을 할 수있는 방법이 있습니다. 그러나 당신이 그것을 사용해야한다면, 당신은 나쁜 프로그래머이거나 나쁜 프로그래머가 작성한 코드를 사용하고 있습니다. 따라서 나쁜 프로그래머가되는 것을 멈추거나이 나쁜 코드의 사용을 멈추는 것에 대해 생각해야합니다. 이 솔루션은 다른 방법이없는 상황에만 해당됩니다.
Thread f = <A thread to be stopped>
Method m = Thread.class.getDeclaredMethod( "stop0" , new Class[]{Object.class} );
m.setAccessible( true );
m.invoke( f , new ThreadDeath() );
Thread.stop
더 이상 사용되지 않더라도 대중에게 전화를 걸 수 있기 때문에이 작업을 수행 할 이유가 전혀 없습니다 .
Thread.stop
는 동일하지만 액세스 및 권한을 확인합니다. 사용 Thread.stop
은 다소 명백하며 Thread.stop0
그 대신 왜 내가 사용했는지 이유를 기억하지 못합니다 . 어쩌면 Thread.stop
나의 특별한 경우 (웹 로직에서 Java 6)을 위해 작동하지 않았다. 또는 Thread.stop
더 이상 사용되지 않아 경고가 발생할 수 있습니다.
누적 된 주석을 기반으로 여러 관측 값을 추가하고 싶습니다.
Thread.stop()
보안 관리자가 허용하면 스레드를 중지합니다.Thread.stop()
위험합니다. JEE 환경에서 작업 중이고 호출되는 코드를 제어 할 수없는 경우에는 필요할 수 있습니다. 보다Thread.stop이 더 이상 사용되지 않는 이유를 .stop()
호출 스레드 에서 새 ThreadDeathError
오류를 생성 한 다음 대상 에서 해당 오류를 발생시킵니다. 스레드 . 따라서 스택 추적은 일반적으로 가치가 없습니다.stop()
에서 보안 관리자를 stop1()
확인한 다음 해당 호출 을 호출합니다 stop0()
. stop0()
네이티브 코드입니다.Thread.stop()
현재는 아직 제거되지 않았지만Thread.stop(Throwable)
Java 11에서는 제거되었습니다. ( mailing list , JDK-8204243 )나는 투표했다 Thread.stop()
.
예를 들어 네트워크 요청과 같이 오래 지속되는 작업이 있습니다. 아마도 응답을 기다리는 중이지만 시간이 걸리고 사용자가 다른 UI로 이동했을 수 있습니다. 이 대기 스레드는 이제 a) 쓸모가 없습니다. b) 잠재적 인 문제입니다. 결과를 얻을 때 완전히 쓸모없고 오류가 발생할 수있는 콜백을 트리거하기 때문입니다.
이 모든 것 그리고 그는 CPU를 많이 사용하는 응답 처리를 할 수 있습니다. 그리고 당신은 개발자로서 던질 수 없기 때문에 그것을 막을 수도 없습니다.if (Thread.currentThread().isInterrupted())
는 모든 코드에 줄을 .
따라서 스레드를 강제로 중지 할 수 없다는 것은 이상합니다.
Thread.stop()
어쨌든 안전하게 전화를 걸 수 없습니다 . 에 투표하지 않고 Thread.stop()
, 안전하게 중단하기 위해 오랜 시간이 걸릴 수있는 모든 작업을 수행하는 모든 사람을 요구하고 있습니다. 그리고 그것은 좋은 생각 일 수도 있지만 Thread.stop()
안전한 낙태를 요청하는 방법으로 구현하는 것과는 아무런 관련이 없습니다 . 우리는 이미 interrupt
그렇게했습니다.
stop
.
문제는 다소 모호하다. "필요할 때 스레드가 실행을 중지하도록 프로그램을 작성하는 방법"을 의미 한 경우 다양한 기타 응답이 도움이됩니다. 그러나 "서버에 응급 상황이 발생했다면 지금 다시 시작할 수없고 죽을 특정 스레드 만 있으면됩니다."라고 말한 경우 다음과 같은 모니터링 도구와 일치하는 중재 도구가 필요합니다.jstack
.
이를 위해 jkillthread를 만들었 습니다 . 사용법은 해당 지침을 참조하십시오.
물론 완전히 신뢰할 수없는 코드를 실행하는 경우가 있습니다. (개인적으로 업로드 한 스크립트를 Java 환경에서 실행할 수있게함으로써이 문제를 해결할 수 있습니다. 예, 보안 경보 벨이 울리지 만 응용 프로그램의 일부입니다.)이 불행한 경우에 우선 스크립트 작성자에게 물어 보면 희망이 있습니다. 부울 런 / 런런 금지 신호를 존중합니다. 예를 들어, 시간 초과보다 오래 실행되는 경우 스레드에서 stop 메소드를 호출하는 것이 괜찮은 유일한 안전 장치입니다.
그러나 코드가 ThreadDeath 오류 (또는 명시 적으로 throw하는 예외)를 포착 할 수 있고 신사 스레드처럼 다시 throw하지 않기 때문에 이것은 "괜찮은"것이며 절대적이지는 않습니다. 결론은 AFAIA이며 절대 안전 장치는 없습니다.
스레드를 정상적으로 죽일 방법은 없습니다.
스레드를 중단하려고 할 수 있습니다. 일반적인 전략 중 하나는 독 약을 사용하여 스레드 자체를 중지하라는 메시지를 보내는 것입니다.
public class CancelSupport {
public static class CommandExecutor implements Runnable {
private BlockingQueue<String> queue;
public static final String POISON_PILL = “stopnow”;
public CommandExecutor(BlockingQueue<String> queue) {
this.queue=queue;
}
@Override
public void run() {
boolean stop=false;
while(!stop) {
try {
String command=queue.take();
if(POISON_PILL.equals(command)) {
stop=true;
} else {
// do command
System.out.println(command);
}
} catch (InterruptedException e) {
stop=true;
}
}
System.out.println(“Stopping execution”);
}
}
}
BlockingQueue<String> queue=new LinkedBlockingQueue<String>();
Thread t=new Thread(new CommandExecutor(queue));
queue.put(“hello”);
queue.put(“world”);
t.start();
Thread.sleep(1000);
queue.put(“stopnow”);
일반적으로 스레드를 죽이거나 중지하거나 중단하지 않으며 (또는 중단되었는지 확인) 자연스럽게 종료하십시오.
간단하다. run () 메소드 내에서 (휘발성) 부울 변수와 함께 루프를 사용하여 스레드의 활동을 제어 할 수 있습니다. 활성 스레드에서 기본 스레드로 돌아가서 중지 할 수도 있습니다.
이렇게하면 스레드를 정상적으로 죽일 수 있습니다 :).
갑작스러운 스레드 종료 시도는 잘 알려진 나쁜 프로그래밍 방식과 응용 프로그램 디자인이 불량하다는 증거입니다. 다중 스레드 응용 프로그램의 모든 스레드는 명시 적 및 암시 적으로 동일한 프로세스 상태를 공유하고 일관성을 유지하기 위해 서로 협력해야합니다. 그렇지 않으면 응용 프로그램이 실제로 진단하기 어려운 버그에 취약합니다. 따라서 신중하고 명확한 응용 프로그램 설계를 통해 이러한 일관성을 보장하는 것은 개발자의 책임입니다.
제어 된 스레드 종료에 대한 두 가지 주요 올바른 솔루션이 있습니다.
갑작스러운 스레드 종료와 관련된 문제에 대한 자세하고 자세한 설명과 제어 스레드 종료에 대한 잘못되고 올바른 솔루션의 예는 여기에서 찾을 수 있습니다.
Android에서 인터럽트가 작동하지 않았 으므로이 방법을 사용하여 완벽하게 작동합니다.
boolean shouldCheckUpdates = true;
private void startupCheckForUpdatesEveryFewSeconds() {
Thread t = new Thread(new CheckUpdates());
t.start();
}
private class CheckUpdates implements Runnable{
public void run() {
while (shouldCheckUpdates){
//Thread sleep 3 seconds
System.out.println("Do your thing here");
}
}
}
public void stop(){
shouldCheckUpdates = false;
}
'실을 죽이는 것'은 올바른 문구가 아닙니다. 다음은 마음대로 스레드의 완성 / 종료를 구현할 수있는 한 가지 방법입니다.
내가 사용한 Runnable :
class TaskThread implements Runnable {
boolean shouldStop;
public TaskThread(boolean shouldStop) {
this.shouldStop = shouldStop;
}
@Override
public void run() {
System.out.println("Thread has started");
while (!shouldStop) {
// do something
}
System.out.println("Thread has ended");
}
public void stop() {
shouldStop = true;
}
}
트리거링 클래스 :
public class ThreadStop {
public static void main(String[] args) {
System.out.println("Start");
// Start the thread
TaskThread task = new TaskThread(false);
Thread t = new Thread(task);
t.start();
// Stop the thread
task.stop();
System.out.println("End");
}
}
Thread.stop은 더 이상 사용되지 않으므로 java에서 스레드를 어떻게 중지합니까?
항상 인터럽트 방법과 미래를 사용하여 취소를 요청하십시오.
Callable < String > callable = new Callable < String > () {
@Override
public String call() throws Exception {
String result = "";
try {
//assume below take method is blocked as no work is produced.
result = queue.take();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return result;
}
};
Future future = executor.submit(callable);
try {
String result = future.get(5, TimeUnit.SECONDS);
} catch (TimeoutException e) {
logger.error("Thread timedout!");
return "";
} finally {
//this will call interrupt on queue which will abort the operation.
//if it completes before time out, it has no side effects
future.cancel(true);
}
public interface CustomCallable < T > extends Callable < T > {
void cancel();
RunnableFuture < T > newTask();
}
public class CustomExecutorPool extends ThreadPoolExecutor {
protected < T > RunnableFuture < T > newTaskFor(Callable < T > callable) {
if (callable instanceof CancellableTask)
return ((CancellableTask < T > ) callable).newTask();
else
return super.newTaskFor(callable);
}
}
public abstract class UnblockingIOTask < T > implements CustomCallable < T > {
public synchronized void cancel() {
try {
obj.close();
} catch (IOException e) {
logger.error("io exception", e);
}
}
public RunnableFuture < T > newTask() {
return new FutureTask < T > (this) {
public boolean cancel(boolean mayInterruptIfRunning) {
try {
this.cancel();
} finally {
return super.cancel(mayInterruptIfRunning);
}
}
};
}
}