2009-11-09 3 views
4

가끔 타사 독점 JDBC 드라이버에서 connect()를 호출하면 절대 반환되지 않으며 스택 추적은 소켓 읽기 (일반적으로) 대기를 기다리고 있음을 보여줍니다. 다른 스레드에서이 작업을 강제로 취소하는 일반적인 방법이 있습니까? 그것은 Thread.interrupt()가 작동하지 않도록 블로킹 I/O 콜이며 독점 코드 내부에서 생성되었으므로 액세스 할 수 없기 때문에 소켓을 직접 닫을 수 없습니다.connect() 호출 중단/취소

이기종 DB 환경 (Oracle, MySQL, Sybase 등)을 가지고 있기 때문에 일반적인 솔루션을 찾고 있습니다. 그러나 운전자 별 제안도 환영합니다. 고마워,

답변

2

연결을 설정하거나 표준 JDBC 인터페이스가 없습니다 JDBC 드라이버가 제한 시간을 지원하는 경우 독점 확장을 사용해야합니다. Oracle JDBC 씬 드라이버의 경우 다음과 같이 할 수 있습니다. 시스템 특성 "oracle.net.CONNECT_TIMEOUT"및 "oracle.jdbc.ReadTimeout"을 설정하거나 이러한 특성이 설정된 DriverManager.getConnection에 Properties 인스턴스를 전달하십시오. 특히 문서화되지는 않았지만 Oracle 고유의 속성은 API documentation에 나열되어 있습니다.

다른 JDBC 드라이버의 경우 설명서에 관련 참조가 포함되어 있어야합니다.

1

적어도 하나의 JDBC 드라이버 (나열된 드라이버 중 하나가 아님)는이 연결 시도가 실행중인 스레드가 중단되면 연결을 완전히 닫습니다. 나는 이것이 모든 운전자를 위해 작동 할 것인지에 관해 모른다.

2

아 ... 폐쇄 소스 라이브러리를 사용하는 기쁨 ...

interrupt() 만약 작동하지 않는, 당신은 시간 제한의 어떤 종류를 설정할 수 없습니다, 나는 그것을 할 수있는 안전한 방법이 없다고 생각 . Thread.kill()을 호출하면이 작업을 수행 할 수 있지만이 방법은 안전하지 않기 때문에 더 이상 사용되지 않습니다. 그리고 이것은 안전하지 않은 - Thread.kill()이 되돌아 와서 당신을 물을 수있는 종류의 시나리오입니다.

고정 된 스레드를 포기하도록 응용 프로그램을 코딩하는 것이 좋습니다. 응용 프로그램이 반복적으로 DB에 연결을 시도하지 않는다고 가정하면 걸린 스레드는 큰 오버 헤드가 아닙니다.

더 나은 JDBC 드라이버를 사용하십시오. (문 밖으로 나올 때, 운전자가 너무 유연하지 않다는 것에 대해 공급자에게 불평하십시오. 누군가가 당신의 말을 경청 할 수있는 약간의 기회가 있습니다 ...)

+0

하나의 옵션은 내가 생각 해본 적이 있어요하지만 실제로 Thread.stop를 때문에 스레드를 포기 같은 일 금액()는 I/O 작업을 차단하는 데 영향을주지 않습니다. – Dan

0

이것은 JDBC 드라이버가 아닌 Java에서 발생하는 문제입니다. 특정 상황에서 소켓 연결 호출은 제한 시간 매개 변수를 무시하고 반환하는 데 몇 분이 걸릴 수 있습니다. 방화벽이 포트를 차단할 때 이런 일이 발생합니다. 그것은 모든 TCP 연결 (HTTP, RMI)에 발생합니다.

내가 찾을 수있는 유일한 솔루션은이 같은 다른 스레드에서 연결을 열 수 있습니다

,

private static final ExecutorService THREADPOOL 
     = Executors.newCachedThreadPool(); 

    private static <T> T call(Callable<T> c, long timeout, TimeUnit timeUnit) 
     throws InterruptedException, ExecutionException, TimeoutException 
    { 
     FutureTask<T> t = new FutureTask<T>(c); 
     THREADPOOL.execute(t); 
     return t.get(timeout, timeUnit); 
    } 

    try { 
     Data data = call(new Callable<Data>() { 
      public Data call() throws Exception 
      { 
       // Open connection, get data here 
       return data; 
      }, 2, TimeUnit.SECONDS); 
    } catch (TimeoutException e) { 
     System.err.println("Data call timed-out"); 
    } 
+0

나는 그것을 시도 할 것이다. 서블릿 컨테이너의 관리되는 풀에 있기 때문에 그냥 주 스레드를 버릴 수는 없지만 작동해야합니다. – Dan