Código fuente local de subprocesos
Recientemente vi un fragmento de código en stackoverflow.
A primera vista parecía una tontería, pero cuando lo entendí, ¡inmediatamente me arrodillé!
Primero permítame mostrarle cuál es esta pregunta sobre stackoverflow y luego cite este código:
La pregunta es muy simple, solo una oración:
¿Puede Alguien me explica: ¿por qué este código imprime hola mundo usando una cadena aleatoria?
El código también es muy sencillo. Déjame sacarlo y mostrártelo:
También puedes pegar el código anterior directamente en tu entorno de ejecución y ejecutarlo para ver si también genera hola mundo:
p>Déjame preguntarte esto: Incluso si te hubiera dado todo el código, ¿te habrías sentido perdido cuando vi "Hello World" por primera vez?
Respondió Gao Zan.
La respuesta de Gao Zan también es muy simple, solo dos oraciones.
Déjame traducirlo para ti. Este tipo dijo:
Cuando llamamos al constructor de Random, obtenemos un parámetro "semilla". Por ejemplo, en este ejemplo: -229985452 o -147909649.
Luego, Random generará números aleatorios a partir del valor inicial especificado.
Y cada objeto aleatorio construido con la misma semilla generará números según el mismo patrón.
No lo vi muy claro, ¿verdad?
No importa, te daré un fragmento de código y de repente entenderás de qué trata el párrafo anterior:
Este código se ejecuta en mi máquina y los resultados son los siguientes:
Si corres con él, el resultado de tu carrera será así.
¿A qué se debe esto?
La respuesta está escrita en Javadoc:
En el código anterior, los dos -229985452 son la misma semilla y las tres llamadas a nextInt() son la misma secuencia de llamadas.
Así, generan y devuelven números idénticos aparentemente aleatorios.
Nuestro uso normal en el programa debería ser así:
Cuando se usa new Random(), no se especifica ningún valor.
Todos sabemos que Random es un algoritmo pseudoaleatorio. Especificar los parámetros semilla durante la construcción es un algoritmo más pseudoaleatorio.
Porque si puedo adivinar tu semilla, o si tu semilla se filtra, entonces, en teoría, puedo adivinar tu secuencia de generación de números aleatorios.
He demostrado esto en el código anterior.
Antes te expliqué brevemente los puntos clave de las "semillas", y luego vuelvo al tema de la degustación, y probablemente puedas obtener algunas pistas.
Mira principalmente el código en este bucle.
En primer lugar, nextInt(27) define que el número k devuelto actualmente debe ser un número entre [0, 27].
Si se devuelve 0, el ciclo finaliza; en caso contrario, el ciclo finaliza. Luego haz una conversión de tipo.
Luego está el elenco de tipos de caracteres.
Cuando veas que un número cambia al tipo char, debes pensar en el código ascii de forma condicional:
En la tabla de códigos ascii, podemos ver que "96" es el símbolo aquí:
Por lo tanto, el rango del siguiente código es [96 1, 96 26]:
Es decir, [97, 122], que es el código ascii correspondiente a-z .
Entonces, déjame llevarte a desensamblar el código de demostración anterior.
El primero son los primeros cinco retornos de NewRandom (-229985452). Nextint (27) es el siguiente:
Las primeras cinco veces NewRandom devuelve (-147909649).
Nextint (27) es el siguiente:
Entonces, cuando miras la tabla de códigos ascii, puedes ver su letra correspondiente:
Ahora, en cuanto a por qué se genera este código inescrutable "Hola mundo", ¿sé muy bien en mi corazón que es como un espejo?
Compruébalo, esto es sólo una estafa.
Luego hubo un comentario debajo de esta pregunta que me mostró otra forma de abrirla:
Puedes especificar imprimir hola mundo, así que en teoría también puedo especificar escribir otras palabras. .
Por ejemplo, este hermano escribió una frase: El ágil zorro marrón saltó sobre un perro perezoso.
Si se traduce literalmente, significa "un cruce entre un ágil zorro marrón y un perro perezoso", lo que parece una tontería.
Sin embargo, debes saber que mi nivel de inglés es relativamente alto y definitivamente no es fácil ver esta frase aquí.
Así que lo comprobé:
Efectivamente, hay una historia, un truco dentro de un truco.
Después de leer el ejemplo del veloz zorro marrón de este hermano, tengo nuevas ideas.
Dado que puede escribir todas las letras, ¿puedo también escribir las frases específicas que quiero?
Estoy bien, gracias y a ti.
En la respuesta a esta pregunta, el "buen samaritano" ya ha escrito el código para la función de encontrar la semilla correspondiente a la palabra especificada.
Lo publiqué directamente, también puedes usarlo directamente:
Entonces estoy buscando la oración mencionada antes, es muy simple:
Y yo Mientras corría, obviamente sentí que pasé mucho tiempo buscando la palabra "gracias".
¿Por qué?
Déjame contarte una historia. Solo hay una frase, debes haberla escuchado:
El método generateSeed aquí es equivalente a este mono. La palabra gracias es Shakespeare.
En el método generateSeed, "Gracias" siempre se puede organizar mediante la disposición continua y la combinación de 26 letras, pero solo se puede organizar por un corto tiempo.
Cuanto más larga es la palabra, más tiempo tarda.
Por ejemplo, te diré felicidades. Una frase tan larga no ha salido en 23 horas desde las 00:05 hasta ahora:
Pero en teoría, mientras haya. Si hay tiempo suficiente, se encontrará la semilla.
En este punto, deberías comprender completamente por qué el código mencionado anteriormente imprime la cadena aleatoria hola mundo.
¿Crees que quiero llevarte a ver el código fuente?
No, principalmente te llevo a comer melón.
Primero, eche un vistazo al constructor aleatorio sin parámetros:
Hola chicos, resulta ser un shell "sin parámetros". De hecho, hice una semilla yo mismo y luego la llamé. Los parámetros. Método de construcción.
Acabo de agregar la variable "System.nanoTime()" durante la compilación para que la semilla parezca un poco aleatoria.
Espera un momento, ¿no existía antes un método “seedUniquifier”?
Este método es así:
Hola chicos, cuando lo vi por primera vez, mi cabeza era muy grande. Aquí hay dos "números mágicos":
¿No entiendes esto?
Nunca te decidas, Stark Flo
Una búsqueda te llevará a este lugar:
En esta pregunta, dijo que él también estaba desconcertado por la dos números, buscó en Internet y encontró muy poca información relevante. Pero encontré un artículo que mencionaba un "número mágico" muy cercano:
Los números mencionados en el artículo son los siguientes:
¿Lo viste?
Al número en este código fuente de Java le falta un "1". ¿Qué pasó? No se pueden cometer errores al copiar, ¿verdad?
Aquí están las respuestas muy elogiosas:
"Esto parece un error".
Interesante.
Si dijeras que este fue el código que mi hermano copió cuando escribía el código fuente de Java, me emocionaría.
Inmediatamente fui a la página de errores de Java y busqué esa cadena de números. Fue realmente inesperado:
En la descripción de este error, me llamó la atención sobre la fuente. Este lugar en el código:
Resulta que la anotación en este lugar representa un documento, por lo que la fuente de este número debe estar oculta en este documento.
Espera un momento, ¿por qué creo que el nombre de este artículo me suena familiar?
El enlace mencionado en el stackoverflow anterior es una dirección en papel:
Vea si el nombre de este documento es el mismo que el comentario en Java:
Eso es Definitivamente es lo mismo, solo que uno en minúscula y otro en mayúscula.
Así que aquí está el verdadero negocio. Esta es realmente la primera vez que comencé a escribir el número de copia de mi hermano en Java y perdí un "1".
Además, incluso puedo imaginar que cuando el hermano escribió esta parte del código fuente, pegó el número "1178349727652981" y encontró: Oye, ¿por qué hay dos 1 delante? Fue copiado y eliminado.
En cuanto a eliminar este "1", ¿qué problemas causará?
De todos modos, hay un problema relacionado aquí, que dice que la aleatoriedad de las llamadas simultáneas a new Random() no es lo suficientemente alta.
No estudié esto. Si estás interesado, puedes ir a echar un vistazo. Sólo soy responsable de llevarte a comer melón.
Entonces, basándose en este "melón", el funcionario hizo una modificación a este código:
Resulta que tengo las versiones JDK 15 y JDK 8 del código aquí. Cuando lo vi, en realidad era la diferencia de "1":
En cuanto a los números aleatorios, Random rara vez se usa hoy en día.
¿Es bueno usar ThreadLocalRandom directamente?
¿Qué, te negaste?