Cảnh báo : Các chương trình này là bom nhân bản (một dạng bom ít nguy hiểm nhưng vẫn nguy hiểm); như vậy, không chạy chúng trên một hệ thống sản xuất mà không có giới hạn tài nguyên hoặc hộp cát . Bom nhân bản tạo ra các luồng trong một vòng lặp (trái ngược với bom ngã ba, tạo ra các quy trình trong một vòng lặp), do đó bạn có thể ngăn chặn chúng đơn giản bằng cách giết quá trình trong câu hỏi (làm cho chúng ít nguy hiểm hơn bom ngã ba, rất khó để dọn sạch); nhưng họ có thể sẽ buộc hầu hết CPU của bạn cho đến khi bạn quản lý để làm như vậy (hoặc cho đến khi chương trình chiến thắng và tự nhiên thoát ra). Yêu cầu HĐH của bạn đặt giới hạn về dung lượng bộ nhớ và thời gian CPU mà các chương trình này được phép sử dụng sẽ tạo ra một môi trường an toàn để kiểm tra chúng.
Java (OpenJDK 8) , 65 60 byte (với một sửa đổi nhỏ cho trình bao bọc)
Thread x=Thread.currentThread();new Thread(x::stop).start();
Hãy thử trực tuyến!
Yêu cầu cả hai trường hợp catch (Exception …)
trong câu hỏi được thay đổi thành catch (Throwable …)
. Về lý thuyết, điều này sẽ an toàn hơn , không ít hơn, nhưng nó cho phép giải pháp này khả thi.
Tôi đã lưu 5 byte qua phiên bản đầu tiên của câu trả lời này bằng cách sử dụng tham chiếu phương thức thay vì lambda.
Java 4, 104 byte (chưa được kiểm tra, sẽ hoạt động với trình bao bọc gốc)
final Thread x=Thread.currentThread();new Thread(){public void run(){x.stop(new Exception());}}.start();
Hãy thử trực tuyến! (liên kết đến bản triển khai Java 8, do đó sẽ không hoạt động)
Sử dụng các tính năng đã bị xóa khỏi các phiên bản Java hiện đại, có thể giải quyết ngay cả phiên bản câu đố cần có Exception
. Có lẽ, ít nhất. (Hiện tại Java 4 đã rất cũ và tôi không thể nhớ những tính năng nào nó đã làm và không chứa. Như có thể thấy, có rất nhiều tính năng trong Java hồi đó và do đó nó dài dòng hơn; chúng tôi không có lambdas, vì vậy tôi phải tạo ra một lớp bên trong.)
Giải thích
Hầu hết các giải pháp cho câu hỏi này là trong C # (cùng với giải pháp Java gian lận thông qua việc sử dụng dấu ngoặc không cân bằng làm hình thức tiêm mã và giải pháp Perl không có trong Java). Vì vậy, tôi nghĩ rằng sẽ rất đáng để thử chỉ ra cách giải câu đố này "đúng" trong Java.
Cả hai chương trình đều giống hệt nhau một cách hiệu quả (do đó, thực tế là chương trình đầu tiên hoạt động mang lại cho tôi sự tin tưởng cao rằng chương trình thứ hai cũng hoạt động, trừ khi tôi vô tình sử dụng một tính năng không phải là Java-4; Thread#stop
không được dùng trong Java 5).
Thread#stop
Phương thức của Java hoạt động, đằng sau hậu trường, thông qua việc khiến cho một cú ném có thể bị ném vào luồng đang nghi vấn. Mục đích có thể ném được nhằm mục đích là ThreadDeath
(một Error
, cụ thể là vì mọi người thường cố gắng bắt ngoại lệ và các nhà thiết kế của Java không muốn điều đó xảy ra), mặc dù nó cho phép bạn ném bất cứ thứ gì (hoặc đã từng sử dụng; vào một lúc nào đó sau API được thiết kế, các nhà thiết kế của Java nhận ra rằng đây là một ý tưởng cực kỳ tồi tệ và đã loại bỏ phiên bản của phương thức đưa các đối số hoàn toàn). Tất nhiên, ngay cả phiên bản ném ThreadDeath
là một hoạt động khá rủi ro mà bạn có thể đảm bảo một vài điều (ví dụ, nó cho phép bạn giải câu đố này, một điều "không nên" có thể), vì vậy bạn không được phép sử dụng nó, nhưng kể từ Java 8, nó vẫn hoạt động.
Chương trình này hoạt động bằng cách sinh ra một luồng mới và yêu cầu nó buộc phải ném ngoại lệ trở lại luồng chính. Nếu chúng ta may mắn, nó sẽ làm điều đó vào một thời điểm khi chúng ta ở bên ngoài catch
khối bên trong (chúng ta không thể thoát khỏi catch
khối bên ngoài cho đến khi chương trình kết thúc, bởi vì có một vòng lặp xung quanh nó). Vì chúng ta đã thêm vòng lặp một cách thuận tiện, nên tiết kiệm byte chỉ đơn giản là sử dụng vòng lặp đó để cho phép chúng ta tiếp tục tạo chủ đề, với hy vọng rằng một trong số chúng cuối cùng sẽ đạt được thời gian chính xác. Điều này thường xảy ra trong vài giây.
(Lưu ý về TIO: phiên bản hiện tại của TIO khá có xu hướng giết chương trình này sớm khi thực hiện, có lẽ là do tất cả các luồng được tạo. Nó có thể hoạt động trên TIO, nhưng không hoạt động đáng tin cậy, do đó thường cần một vài lần thử nhận đầu ra "Bạn đã thắng!".)