警告:这些程序是克隆炸弹(一种不太危险但仍然很危险的叉子炸弹形式);因此,请勿在没有沙箱或资源限制的生产系统上运行它们。克隆炸弹会在一个循环中创建线程(与叉炸弹相反,它会在一个循环中创建进程),因此您可以简单地通过杀死相关进程来停止它们(这使它们比叉炸弹的危险性低得多,这很难做到)清理); 但是它们可能会占用您的大部分CPU,直到您设法这样做为止(或直到程序本身赢并自然退出)。要求操作系统对允许使用这些程序的内存量和CPU时间进行限制,应该会创建一个安全的环境来对其进行测试。
Thread x=Thread.currentThread();new Thread(x::stop).start();
在线尝试!
要求catch (Exception …)
将问题中的两个实例都更改为catch (Throwable …)
。理论上应该是更安全,而不是更少,但是它使这种解决方案成为可能。
通过使用方法引用而不是lambda,我在此答案的第一个版本上节省了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中的功能较少,因此更加冗长;我们没有lambdas,因此我必须创建一个内部类。)
说明
这个问题的大多数解决方案都在C#中(连同通过使用不平衡括号作为代码注入形式作弊的Java解决方案以及Java中也不存在的Perl解决方案)。因此,我认为值得尝试展示如何在Java中“适当”解决这个难题。
这两个程序实际上是相同的(因此,第一个程序可以工作的事实使我很有信心,第二个程序也可以工作,除非我不小心使用了非Java-4功能; Thread#stop
很有在Java 5中已弃用)。
Java的Thread#stop
方法在后台通过使throwable被抛出到相关线程中而起作用。尽管它允许您抛出任何东西(或习惯于;在API被使用之后的某个时刻),但为此目的而设计的throwable是ThreadDeath
(Error
特别是因为人们经常尝试全面捕获异常,而Java的设计师不希望发生这种情况)。在设计时,Java的设计师意识到这是一个非常糟糕的主意,因此删除了直接使用参数的方法版本。当然,即使抛出的版本ThreadDeath
也是相当冒险的操作,您几乎无法保证(例如,它可以解决此难题,而“不可能”解决),所以您不应该这样做使用它,但是从Java 8开始,它仍然有效。
该程序通过产生一个新线程,并要求其将异常强制返回主线程来工作。如果幸运的话,它会在我们进入内部catch
块之外的某个时间点执行此操作(catch
在程序结束之前我们无法逃避外部块,因为周围有一个循环)。因为我们已经方便地添加了循环,所以简单地使用该循环以允许我们继续创建线程是节省字节的,希望它们中的一个最终会达到正确的时间。通常,这似乎会在几秒钟内发生。
(TIO注意:当前版本的TIO倾向于在执行该程序的早期就终止该程序,大概是由于创建了所有线程。它可以在TIO上运行,但不能可靠地运行,因此通常需要进行几次尝试才能完成)获得“您赢了!”输出。)