Предупреждение : Эти программы представляют собой бомбы-клоны (разновидность менее опасной, но все же опасной формы вилочной бомбы); как таковые, не запускайте их в производственной системе без песочницы или ограничений ресурсов . Клонированные бомбы создают потоки в цикле (в отличие от вилочных бомб, которые создают процессы в цикле), таким образом, вы можете остановить их, просто убив рассматриваемый процесс (делая их намного менее опасными, чем вилочные бомбы, что может быть очень трудно проясняться); но они, скорее всего, будут связывать большую часть вашего процессора, пока вам не удастся это сделать (или пока программа не выйдет и не выйдет естественным путем сама). Если ваша операционная система ограничивает объем памяти и процессорного времени, которые эти программы могут использовать, должна создать безопасную среду для их тестирования.
Java (OpenJDK 8) , 65 60 байт (с небольшой модификацией оболочки)
Thread x=Thread.currentThread();new Thread(x::stop).start();
Попробуйте онлайн!
Требует, чтобы оба экземпляра catch (Exception …)
в вопросе были изменены на catch (Throwable …)
. Теоретически это должно быть более безопасным, а не менее, но оно позволяет сделать это решение возможным.
Я сохранил 5 байтов поверх первой версии этого ответа, используя ссылку на метод, а не лямбду.
Java 4, 104 байта (не проверено, должно работать с оригинальной оболочкой)
final Thread x=Thread.currentThread();new Thread(){public void run(){x.stop(new Exception());}}.start();
Попробуйте онлайн! (ссылка идет на реализацию Java 8, поэтому не будет работать)
Используя функции, которые были удалены из современных версий Java, можно решить даже ту версию головоломки, которая требует Exception
. Возможно, по крайней мере. (Java 4 сейчас очень старая, и я не могу вспомнить, какие функции она имела и не содержала. Как можно видеть, тогда в Java было намного меньше функций, и поэтому она была более многословной; у нас не было лямбды, поэтому мне пришлось создать внутренний класс.)
Пояснения
Большинство решений этого вопроса находятся на C # (вместе с решением Java, которое обманывает, используя несбалансированные скобки в качестве формы внедрения кода, и решением Perl, которое также отсутствует в Java). Поэтому я подумал, что стоит попытаться показать, как эта головоломка может быть решена «правильно» и в Java.
Обе программы фактически идентичны (поэтому тот факт, что первая программа работает, дает мне высокую уверенность в том, что вторая программа тоже будет работать, если только я случайно не использовал функцию, отличную от Java-4; Thread#stop
в Java 5 она устарела).
Thread#stop
Метод Java работает за кулисами, заставляя бросаемый объект бросаться в рассматриваемый поток. Функция throwable предназначена для этой цели ThreadDeath
(в Error
частности, потому что люди часто пытаются скрыть исключения, а разработчики Java не хотят, чтобы это происходило), хотя она позволяет вам что-либо генерировать (или раньше) в некоторый момент после того, как API был Разработчики Java поняли, что это невероятно плохая идея, и удалили версию метода, в которой аргументы принимаются прямо). Конечно, даже версия, которую выкидывает, ThreadDeath
является довольно рискованной операцией, в отношении которой вы можете дать несколько гарантий (например, она позволяет решить эту головоломку, что-то, что «не должно быть» возможно), поэтому вы не должны используйте его, но на Java 8 он все еще работает.
Эта программа работает, порождая новый поток и заставляя его принудительно выбросить исключение обратно в основной поток. Если нам повезет, он сделает это в тот момент, когда мы находимся вне внутреннего catch
блока (мы не можем выйти из внешнего catch
блока, пока программа не завершится, потому что вокруг него есть цикл). Поскольку у нас уже удобно добавлен цикл, экономия байтов состоит в том, чтобы просто использовать этот цикл, чтобы позволить нам продолжать создавать потоки в надежде, что один из них в конечном итоге достигнет правильного времени. Обычно это происходит в течение нескольких секунд.
(Примечание TIO: текущая версия TIO довольно склонна убивать эту программу на ранних этапах ее выполнения, вероятно, из-за всех создаваемых потоков. Она может работать на TIO, но не работает надежно, поэтому часто требуется несколько попыток получите вывод «Вы выиграли!».)