Для завершения выполнения и освобождения ресурсов потоков в Java можно использовать метод interrupt() или метод join().
1. Метод interrupt(): вызов этого метода приведет к установке флага прерывания потока. После этого поток может проверять этот флаг и завершить свою работу самостоятельно.
Пример использования:
```
Thread thread = new Thread(() -> {
// выполнение кода
});
thread.start();
// прервать выполнение потока
thread.interrupt();
```
2. Метод join(): вызов этого метода приостановит выполнение текущего потока и дождется завершения работы другого потока.
Пример использования:
```
Thread thread = new Thread(() -> {
// выполнение кода
});
thread.start();
// дождаться завершения потока
thread.join();
```
Для правильного удаления потоков из программы и предотвращения утечек памяти, необходимо следить за их жизненным циклом и убедиться, что они завершают свою работу и освобождают ресурсы. Это можно сделать, например, вызывая метод join() для ожидания завершения потока, или устанавливая флаг прерывания и проверяя его значение внутри потока.
Также рекомендуется избегать создания большого количества потоков, если они необходимы, можно использовать пул потоков (ThreadPoolExecutor), который позволяет переиспользовать потоки и управлять их жизненным циклом менее затратно.