Java Thread, как освободить ресурс, когда поток выполнен

У меня есть класс Java, который расширяется от Thread, и, например, я хочу отправить сообщение в очередь, но хочу повторно использовать Producer для каждого потока. Не закрывайте его, пока не будет выполнено Thread.

public class Producer extends Thread {
    private final QueueProducer producer;

    public Producer() {
        Properties props = new Properties();
        producer = new QueueProducer(props);
    }

    public void send(String message) {
        producer.send(message);
    }

    // close?
}

Для этого фрагмента кода, как я могу вызвать метод закрытия?


person ttt    schedule 26.07.2018    source источник
comment
Вам нужно освободить все ресурсы в конце метода run(), так как это метод, который выполняется при запуске потока.   -  person Ivan    schedule 26.07.2018
comment
Вы даже можете создать и ограничить производителя блоком try-with-resources внутри блока run. И почему send общедоступен? Вызывают ли другие потоки методы в этом экземпляре Thread? Это может означать неприятности.   -  person Thilo    schedule 26.07.2018
comment
Так почему же здесь не переопределен метод run? и почему бы вам просто не закрыть то, что вы используете, в конце метода запуска?   -  person Nathan Hughes    schedule 26.07.2018
comment
@Thilo, извините, send не должно быть общедоступным, это вызывается только внутри run. Могу ли я повторно использовать один и тот же экземпляр QueueProducer, если я ограничу область внутри run?   -  person ttt    schedule 26.07.2018


Ответы (1)


Если QueueProducer не реализует Closeable и не предоставляет метод для закрытия своих ресурсов, вы не можете закрыть его явно. Лучший способ - ограничить его область действия внутри метода запуска, следовательно, он имеет право на сборщик мусора.

Однако, если он выполняет AutoCloseable или Closeable, то оберните QueueProducer блоком try-with-resources, чтобы автоматически закрыть его после использования.

public void run(){

    try(QueueProducer qp = producer){
        //do operation on qp
    }
}

Или сделать Producer для реализации Closeable. В его переопределенном методе close вместо этого закроется QueueProducer. Например:-

class Producer extends Closeable{

   private final QueueProducer qp;

   ....

   @Override
   public void close(){

      if(qp!=null){
         qp.close();
      }
   }
}

Это похоже на BufferedReader, метод close которого закрывает внутренний объект Reader. Таким образом, QueueProducer остается пригодным для использования до тех пор, пока клиент не закроет Producer сам.

person Awan Biru    schedule 26.07.2018
comment
Такие ресурсы, как соединения с базой данных и некоторые другие, должны быть закрыты явно. ГК их не закроет - person Ivan; 26.07.2018
comment
Да, и большинство из них либо AutoCloseable, либо снабжены своего рода методом close(). Если забыть закрыть, это будет катастрофой, так как ресурсы, такие как сокет, соединение и т. д.2, останутся занятыми. - person Awan Biru; 26.07.2018
comment
Да, QueueProducer реализует AutoCloseable. Но дело в том, что я не хочу вызывать метод close каждый раз после вызова send. Я хочу создать только один экземпляр QueueProducer. При использовании try-with-resources я предполагаю, что close вызывается каждый раз? - person ttt; 26.07.2018
comment
@ttt, модернизируй Producer, чтобы реализовать Closeable. Вместо этого в его переопределенном методе close закройте QueueProducer. Это похоже на BufferedReader, метод close которого закрывает внутреннее состояние Reader. Таким образом, QueueProducer можно использовать до тех пор, пока клиент не закроет QueueProducer. - person Awan Biru; 26.07.2018
comment
@AwanBiru Если это работающее веб-приложение? Должен ли я сделать то же самое? - person ttt; 26.07.2018