Java - остановка длинного потока, который обращается к базе данных

Я запускаю пару потоков, но у меня нет их ссылок, чтобы остановить, сигнализируя или что-то. Например, я могупередать переменную какrunning=false на эти темы, потому что у меня нет их ссылок, но есть их имена.

м, используяThreadGroup и всегда у меня есть ссылка на это. Так что я могу сделать что-то вроде этого. Кажется, это не такт работа.

    Thread[] threads = new Thread[threadGroup.activeCount()];
    int count = threadGroup.enumerate(threads);
    for(int i = 0; i < count; i++){
        threads[i].interrupt();
    }

Это образец моей темы.

    public void run{

         try{
             //myDAO.getRecords();
             //this takes 30seconds to 60
             //returns about 3 millions of records

         }catch(Exception e){
             //log
         }
    }

Когда этот поток выполняется, я хочу остановить его в середине. В любом случае запрос к базе данных выполняется, но я хочу прекратить получать результаты.

Все еще яЯ получаю результаты, даже я звонюinterrupt(), Есть ли другие способы сделать это или я сделал что-то не так? В конечном итоге задача состоит в том, чтобы отменить длительный SQL-запрос из Java.

Ответы на вопрос(5)

и вы хотите остановить выполняющийся запрос, вы могли бы вызвать другой потокcancel по заявлению:

void cancel () выдает SQLException

Cancels this Statement object if both the DBMS and driver support aborting 
an SQL statement. This method can be used by one thread to
cancel a statement that is being executed by another thread.

Throws:
    SQLException - if a database access error occurs or this method is 
    called on a closed Statement 
    SQLFeatureNotSupportedException - if the JDBC driver does not support
    this method

Вы могли бы заставить метод run делегировать вызов DAO другому потоку, и он должен прослушивать прерывание и отмену вызова.

Вотпост, где кто-тоиспользование Spring JdbcTemplate для отмены запроса, Так что это работает для кого-то там (используя MySQL).

Такжепосмотрите этот ответ, описывающий, как запросы отменяются в Oracle.

 sura2k16 мая 2013 г., 16:22
Я понятия не имею об этом, но яЯ собираюсь разобраться в этом.
 Jatin23 июл. 2013 г., 17:45
@NathanHughes лучше было бы использоватьKill_query id (если вообще вам удастся узнатьid). Это не прерывает соединение и только указывает потоку db прекратить выполнение запроса (более подробно об этом говорится в ответе ниже). Я сталкивался с этой ситуацией, и это выглядит лучшим подходом
 Nathan Hughes23 июл. 2013 г., 16:33
@Jatin: разрешить выполнение запроса, когда онне нужно, это также плохо для производительности. Но хорошо осознавать, что связь будет потеряна.
 Jatin23 июл. 2013 г., 16:24
BEWARE. Отмена также убивает соединение. Если вы используете его много, то это ухудшит производительность

Ваш код потока должен пойматьInterruptedExceptionи установите флаг прерывания в вашей теме. Увидетьэтот JavaSpecialist информационный бюллетень для получения дополнительной информации.

  try {
    // ... 
  } 
  catch (InterruptedException ex) {
    Thread.currentThread().interrupt(); // very important
    break;
  }

Поток для прерывания не должен быть привязан к вычислениям. То есть он должен выполнять сетевой ввод-вывод, спящий режим и т. Д., Чтобы поймать и ответить наInterruptedException, Такой цикл какwhile(1) {} победил'не может быть прерываемым.

 sura2k16 мая 2013 г., 16:16
Если DAO кешируетIntrruptedExceptionЯ мог видеть журналы.
 Brian Agnew16 мая 2013 г., 16:14
Я думаю, ваш DAO ловит исключения (и, скорее всего, выиграл 'не справиться с этим сценарием должным образом)
 sura2k16 мая 2013 г., 16:11
Это дает мне этоUnreachable catch block for InterruptedException. This exception is never thrown from the try statement body ошибка компиляции.
 Edward Falk16 мая 2013 г., 17:53
Именно так. InterruptedException фактически только прерывает небольшое количество вещей (например, сон). В общем, вам нужно использоватьisInterrupted () метод обнаружения прерываний.
 sura2k16 мая 2013 г., 16:17
IntrruptedException можно поймать, если естьsleep() вызов.

ремя, после чего поток будет вынужден остановиться.

         @Override public void run() 
           {   // infinite loop to process

                   while(true) // your variable 
                   {                              
                      // We've been interrupted: no more processing.
                      if(Thread.currentThread().isInterrupted()){
                         return;
                       }
                   }

            }
         }
Решение Вопроса

interrupt для потока, который говорит, что ожидание вывода запроса не имеет никакого эффекта, поскольку большинство драйверов JDBC неуязвимы для статуса. Он по-прежнему останется заблокированным, и запрос продолжит выполняться.

cancel уничтожит соединение и поток, выполняющий запрос в базе данных. Время от времени это нормально, но это также убивает связь. Это может создать серьезные проблемы и вскоре станет узким местом.

Альтернативой, но рабочим решением было бы получитьID потока, выполняющего процедуру / запрос (на стороне базы данных) и вызвать:

KILL QUERY id;

KILL QUERY завершает оператор, который в данный момент выполняет соединение, но оставляет само соединение нетронутым.

Чтобы узнать идентификатор, справа В процедуре первая строка должна выглядеть так:SELECT CONNECTION_ID();, Этот идентификатор может быть использован для его прекращения.

 Vadzim08 июн. 2015 г., 15:35
Обратите внимание, что описанный подход уничтожения запросов зависит от MySQL. Вот трюк с Oracle:stackoverflow.com/questions/466963/...

я вызываю прерывание (). Есть ли другие способы сделать это или я сделал что-то не так?

Когда ваша тема была прервана, вам нужно проверитьrun() проходит ли ваша нитьisInterrupted() состояние .

Я думаюinterrupt это лучший способ достичь этого, потому чтоan interrupt will unblock some blocking IO и запросы синхронизации. Индивидуальное решение не может этого сделать.

 sura2k16 мая 2013 г., 16:21
Я делаю это прямо сейчас, но я подумал, что может быть лучше.
 toto216 мая 2013 г., 16:54
Я не уверен в этом вообще, но я бы предположил, чтоinterrupt не будет разблокировать соединение с базой данных. Я знаю, что это не разблокирует сокетное соединение.

Ваш ответ на вопрос