2013-02-13 3 views
0

여러 클라이언트를 처리하기 위해 여러 스레드를 생성하는 간단한 서버를 만들고 있습니다. 서버를 종료 할 때 다양한 스트림과 스레드를 종료하고 닫는 적절한 방법이 궁금합니다.Java : 여러 스레드를 제대로 닫음

서버를 종료하라는 메서드를 실행하는 shutdownHook을 추가했습니다. 서버는 종료 된 모든 스레드에 대해 종료 호출을 브로드 캐스팅합니다.이 스레드는 각 스레드의 "isClosed"부울을 true로 설정합니다.

내가 기대하고있는 것은 run() 메서드의 끝에 도달하여 다시 반복 될 때 각 스레드가 while (! isClosed) 조건을 만족하므로 모든 적절한 소켓/스트림을 닫음으로써 올바르게 종료된다는 것입니다 돌아 오는 중.

그러나 shutdownhook이 완료된 후 프로그램이 종료되어야하므로이 프로그램이 제대로 종료되는지는 알 수 없습니다. 모든 것이 끝내는 메시지를 전달하기 때문에 상당히 일찍 완료됩니다. 이것은 일부 스레드가 제대로 닫히기에 충분한 시간을 얻지 못한다는 것을 의미합니까?

그렇다면 가장 좋은 방법은 shutdownhook이 모든 스레드를 수동으로 닫고 돌아가기 전에 닫았는지 확인하는 것입니다.

+1

기본 접근법은 잘못은 아니지만 스레드에 차단 호출이있는 경우 'Thread.interrupt()'를 조사 할 수도 있습니다. (그리고 모든 호출이 인터럽트 가능하지는 않다는 것을 알고 있어야한다.) 정규 소켓 읽기는 그렇지 않다. – millimoose

+0

만약 non-daemon 쓰레드라면, JVM은 shutdownHook과 상관없이 run 메소드로부터 모든 쓰레드가 반환 될 때까지 종료하지 않을 것이다. 메서드가 반환되었습니다. – Affe

+1

executorervice를 사용하여 스레드를 관리하고 완료되면 executorervice를 종료하십시오. – assylias

답변

0

서버가 종료 된 경우 스레드가 제대로 종료 될 가능성이 충분하지 않을 수도 있습니다. 그러나, 당신이하려고하는 것에 따라 이것은 문제 일 수도 있고 아닐 수도 있습니다. 필요한 정리 작업이 없으면 스레드를 갑자기 종료하면 문제가 발생하지 않으므로 걱정할 필요가 없습니다.

그러나 정리 작업 (예 : 데이터베이스 작성)이 필요한 경우 다른 작업이 필요합니다. 이 작업을 수행하는 가장 좋은 방법은 Executor/ExecutorService 및 관련 항목 (http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Executors.html)을 사용하는 것입니다. 당신의 문제는 이것들에 의해 잘 다루어지며, 스레드 풀 관리와 같은 좋은 공짜 물건을 얻을 수있어 스케일링이 훨씬 쉬워집니다. 모든 클라이언트에 대해 새 스레드를 생성하는 경우 분당 백만 개의 스레드를 만들 수 없기 때문에 나중에 크기를 조정하려고 할 때 큰 문제가 발생합니다.

원시 스레드를 사용하는 경우 Excecutor 항목을 사용하면 약간의 조정이 가능하지만 연구 가치가 있습니다. 행운을 빕니다!

+0

이 권리를 이해하고 있다면 Executors 팩토리를 사용하여 ExecutorService를 간단히 작성합니다. 그런 다음 실행 스레드를 추가하고 서비스가이 스레드를 관리합니다. 그런 다음 닫기를 수행 할 때 응용 프로그램을 닫을 때 shutdown 및 shutdownNow 조합을 사용하여 스레드를 정리합니까? – ImpGuard

+0

네가 맞습니다. 스레드를 생성 할 때 InterruptedException을 적절히 처리하여 스레드에 throw 된 경우 적절한 정리가 수행되도록 할 수 있습니다. InterrupedException를 캐치 한 후에 종료 조건을 재평가하지 않는 thread는, ExecutorService를 사용해 정상적으로 종료하지 않는 경우가 있습니다. 응용 프로그램을 종료하기 전에 종료가 정상적으로 완료되었는지 확인하려면 주 스레드에서 ExecutorService.isTerminated() 또는 awaitTermination()을 사용하여 상태를 쉽게 확인할 수 있습니다. 희망이 도움이됩니다! –

0

ExecutorService을 사용하는 것은 현대적인 방법입니다. 코드에서 너무 많은 부분을 차지합니다.

Here은 좋은 출발점입니다.

+0

고마워요. ExecutorService는 이것을 구현하는 적절한 방법처럼 보입니다. – ImpGuard

0

그런 식으로 유용하기 때문에 shutdownHook이 너무 늦게 발생합니다. 신속하게 완료 할 것으로 예상되며 JVM이 이미 중단되어 데몬 인 경우 기존 스레드를 사용할 수 있습니다.

나는 단지 15-30 초의 연결 스레드에 읽기 시간 제한을 설정합니다. 시간 초과가 (SocketTimeoutException) 발생하면 소켓을 닫고 스레드를 종료하십시오. 물론 클라이언트는 물론 끊어진 연결에 대처해야하지만 이미해야합니다. 그런 다음 종료하려는 경우 새 연결 수락을 중지하십시오 (예 : ServerSocket 닫고 수신 예외 스레드가 결과 예외에 올바르게 대처하도록). 기존의 모든 연결 스레드가 종료되면 JVM이 종료되고 시간 초과 기간에 가장 긴 트랜잭션의 길이를 더한 값을 넘지 않게됩니다. 연결 스레드가 데몬이 아닌지 확인하십시오.

당신이 고객을 생각하지 않는 경우

0

System.exit(). 당신이 당신의 스레드가 스레드를 디먼에 것을 고려 가지고 호출, 중간 거래에 잘려지고. 그냥 t.setdaemon (true)을 추가하십시오. thread의 start 메소드를 호출하기 전에 프로그램이 종료 될 때이 스레드를 종료해야한다면 데몬이 아닌 다른 모든 데몬 스레드가 종료 된 후에 해당 스레드가 종료됩니다. 스레드 풀에서 사용되는 스레드는 데몬이어야하는 스레드의 좋은 예입니다. 그리고 나는 정말로 그것이 당신에게 유용 할 수 있다고 생각합니다.

관련 문제