Java drip let Thread stop execution method

  1. The function of Thread.yield () method is to
  
  suspend the currently executing thread object and execute other threads. What yield () should do is to return the currently running thread to a runnable state to allow other threads with the same priority to get a chance to run. Therefore, the purpose of using yield () is to allow appropriate rotation between threads of the same priority. However, in practice there is no guarantee that yield () will achieve the concession purpose, because the concession thread may also be selected again by the thread scheduler. Conclusion: yield () never caused the thread to go to the wait / sleep / block state. In most cases, yield () will cause the thread running from state to state to run, but there may be no effect
  
  2.Thread.sleep ():
  
  the current thread to sleep for at least the number of milliseconds (although it may be before a specified time Was interrupted).
  
  3. Join () method:
  
  ensure that the current thread stops executing until the thread that the thread joins is completed. However, if the thread it joins does not survive, the current thread does not need to stop. Call the join method of another thread object myThread in the thread myMainThread, which means that the myMainThread thread must wait for the thread of myThread to finish before it can execute. At this time, myThread is inserted, and the invitation must be completed before it is released.
  
  If you are using join (long millis), the parameter indicates the longest waiting time of the myMainThread thread. After this value, it will not wait.
  
  4. Several special circumstances may cause the thread to leave the running state:
  
  1. The thread's run () method carry out.
  
  2. Call the wait () method on the object (not the thread).
  
  3. The thread cannot obtain the lock on the object, it is trying to run the method code of the object
  
  4. The thread scheduler can decide to move the current running state to a runnable state so that another thread can get a chance to run without any reason

  Almost all programming languages ​​provide a "generate a random number" method, that is, calling this method will generate a number, we do not know in advance what number it generates. For example, write the following code in .Net:
  
  Random rand = newRandom ();
  
  Console.WriteLine (rand.Next ()); The
  
  result after running is as follows:
  
  bubuko.com, Bubuko
  
  Next () method is used to return a random number . The same code you execute and my results are likely to be different, and the results of my multiple runs are also likely to be different, this is a random number.
  
  1. Traps
  
  seemingly simple things, there are traps when used. I write the following code to generate 100 random numbers:
  
  for (int i = 0; i <100; i ++)
  
  {
  
  Random rand = new Random ();
  
  Console.WriteLine (rand.Next ());
  
  }
  
  bubuko.com, Bubu buckle is
  
  too weird. The "random numbers" generated are many consecutive ones. What is a "random number"? Someone pointed to "put new Random ()" outside the for loop:
  
  Random rand = newRandom ();
  
  for (int i = 0; i <100; i ++)
  
  {
  
  Console.WriteLine (rand.Next ());
  
  }
  
  Run result:
  
  bubuko.com,
  
  It really works!
  
  2. Why is this?
  
  This starts with the principle of "random number" generation in the computer. We know that computers are very strict, and under certain input conditions, the results produced are uniquely determined and will not be different every time they are executed. So how to use software to generate seemingly uncertain random numbers?
  
  There are many algorithms for generating random numbers, the simplest and most commonly used is the "linear congruence method": the n + 1th number = (the nth number * 29 + 37)% 1000, where% is "find the remainder" Operator. Many people like me have headaches when they see formulas. Let me explain it in code. MyRand is a custom class that generates random numbers:
  
  class MyRand
  
  {
  
  private int seed;
  
  public MyRand (int seed)
  
  {
  
  this.seed = seed ;
  
  }
  
  public int Next ()
  
  {
  
  int next = (seed * 29 + 37)% 1000;
  
  seed = next;
  
  return next;
  
  }
  
  }
  
  Called as follows:
  
  MyRand rand = newMyRand (51);
  
  for (int i = 0; i < 10; i ++)
  
  {
  
  Console.WriteLine (rand.Next ());
  
  } The
  
  execution results are as follows:
  
  At bubuko.com, does
  
  the data generated by Bubuko look "random" anymore. Briefly explain this code: we create an object of MyRand, and then the constructor passes a number 51, this number is assigned to the seed, each time the Next method is called, according to (seed * 29 + 37)% 1000, a random number is calculated , Assign this random number to seed, and then return the generated random number. Then the next time you call Next (), the seed is no longer 51, but the random number generated last time, so that it seems that every time the generated content is "random". Note that the purpose of the "% 1000" remaining budget is to ensure that the generated random number does not exceed 1000.
  
  Of course, whether you run it or every time I run, the output is the same random number, because according to the given initial data 51, we can infer all the "random numbers" generated below can be calculated . This initial data 51 is called "random number seed", this series of 516, 1, 66, 951, 616 ... the number is called "random number sequence". If we change 51 to 52, there will be such a result:
  
  bubuko.com, Bubu buckle
  
  Third, the landlord is a good person, Guiqiu seeds
  
  So how can we make different "random number sequences" every time we run the program? Because the time when we execute the program each time is likely to be different, we can use the current time as a "random number seed"
  
  MyRand rand = newMyRand (Environment.TickCount);
  
  for (int i = 0; i <10; i ++)
  
  {
  
  Console.WriteLine (rand.Next ());
  
  }
  
  Environment.TickCount is "the number of milliseconds that have passed since the system was started". In this way, Environment.TickCount is unlikely to be the same each time the program runs (who can manually start the program twice within a millisecond), so the random number generated each time is different.
  
  bubuko.com, cloth button
  
  Of course if we put new MyRand (Environment.TickCount) in the for loop
  
  :?
  
  for (int i = 0; i <100; i ++)
  
  {
  
  MyRand rand = newMyRand (Environment.TickCount);
  
  Console .WriteLine (rand.Next ());
  
  }
  
  bubuko.com, the
  
  running result of the cloth button becomes "many continuous", the principle is very simple: because the for loop body executes quickly, so every time the environment is executed .TickCount is likely to be the same as last time (two lines of simple code does not take as long as a millisecond event), because this time "random number seed" is the same as the last "random number seed", so Next () is generated The first "random number" is the same. The change from "-320" to "-856" is because a time of one millisecond elapsed when running to "-856".
  
  Fourth, the implementation of each language
  
  We see that the Random class of .Net has a constructor with an int type parameter:
  
  public Random (int Seed)
  
  It is to accept a "random number seed" like the MyRand we wrote. The parameterless constructor we called earlier was constructed by passing the Environment.TickCount class to Random (int Seed). The code is as follows:
  
  public Random (): this (Environment.TickCount)
  
  {
  
  }
  
  Now we finally understand the initial doubts Too.
  
  For the same reason, generating 10 random numbers in C / C ++ should not be called as follows:
  
  int i;
  
  for (i = 0; i <10; i ++)
  
  {
  
  srand ((unsigned) time (NULL));
  
  printf ("% d \ n ", rand ());
  
  }
  
  Instead:
  
  srand ((unsigned) time (NULL)); // Set the current time as" random number seed "
  
  int i;
  
  for (i = 0; i <10; i ++ )
  
  {
  
  printf ("% d \ n", rand ());
  
  }
  
  Fifth, "exotic" Java
  
  Java learners may ask questions. In the lower versions of Java, the following use will be like .Net, C / C ++ Generate the same random number in the same way
  
  :?
  
  For (int i = 0; i <100;
  

  

  
  System.out.println (rand.nextInt ());
  
  }
  
  Because the implementation of the parameterless constructor of the Rand class in low-level Java also uses the current time as the seed:
  
  public Random () {this (System.currentTimeMillis ()); }
  
  But in a high version of Java, such as Java 1.8, the above "error" code execution is okay:
  
  bubuko.com, Bubu buckle
  
  Why? Let's take a look at the implementation code of this Random parameterless constructor:
  
  public Random ()
  
  {
  
  this (seedUniquifier () ^ System.nanoTime ());
  
  } <br>
  
  private static long seedUniquifier () {
  
  for (;;) {
  
  long current = seedUniquifier.get ();
  
  long next = current * 181783497276652981L;
  
  if (seedUniquifier.compareAndSet (current, next))
  
  return next;
  
  }
  
  }
  
  privatestaticfinal AtomicLong seedUniquifier = new AtomicLong (8682522807148012L);
  
  Here is no longer using the current time to do "random number seed", but to use System.nanoTime () the amount of time in nanoseconds and XOR with a number calculated using the atomic weight AtomicLong according to the last call to the constructor . For the explanation of this code, please refer to this article "Decryption Random Number Generator (2)-Linear congruence algorithm from java source code".
  
  The core of the article is to use the static variable AtomicLong to record every time the Random constructor is called. The seed used should not be the same as the last time the Random constructor is called next time.
  
  6. Problems
  
  in high-concurrency systems We have previously analyzed that for a random number generator that uses system time as a "random number seed", if multiple random numbers are to be generated, then a "random number seed" must be shared to avoid it Generate random numbers within a short period of time. However, in some high-concurrency systems, if you don't pay attention, there will be problems. For example, a website generates a verification code on the server side by the following method:
  
  Random rand = new Random ();
  
  Int code = rand.Next ();
  
  when the website is concurrent When the amount is large, there may be many individuals requesting verification codes within a millisecond, which will cause the verification codes requested by these individuals to be repeated, which will bring potential vulnerabilities to the system.
  
  Another example is an article I saw today, "When Random Isn't Random Is Random: Lessons from an Online Poker Game" mentioned "Because the seed of the random number generator is based on the server clock, hackers just need to connect their programs to the server. Clock synchronization can reduce the possible out-of-order to only 200,000. By that time, once the hacker knows 5 cards, he can quickly search for 200,000 possible out-of-order in real time to find the kind in the game. So Once the hacker knows the two cards and the three common cards in his hand, he can guess what cards will come on the turn and river cards, and the cards of other players. "
  
  There are several solutions to this situation:
  
  Use the Random object as a global instance (static). Random in Java is thread-safe (with internal locking); Random in .Net is not thread-safe and requires locking. However, there is a problem that locking will cause slow processing speed. And because the initial seed is determined, the attacker has the possibility to guess the "random number seed" based on the obtained random number sequence.
  
  Because the value of the generated Guid is different every time, some articles on the Internet say that you can create a Guid to calculate its HashCode or MD5 value as the seed: new Random (Guid.NewGuid (). GetHashCode ()). But I think Guid's generation algorithm is deterministic and predictable under sufficient conditions, so that the random numbers generated can also be predicted. Of course it is just my guess, without theoretical proof.
  
  Using "True Random Number Generator", take a look at the next section for decomposition!
  
  7. True random number generator
  
  According to our previous analysis, we know that these so-called random numbers are not really "random", but just look random, so they are called "pseudo-random algorithm". In some occasions with high random requirements, some physical hardware will be used to collect real random physical parameters such as physical noise, cosmic rays, quantum decay, etc. to generate real random numbers.
  
  Of course, some smart people have thought of generating random numbers without the help of adding "random number generator" hardware. When we operate the computer, the movement of the mouse and the typing of the keyboard are unpredictable. It is also unpredictable when the outside world orders the computer what process to execute, what file to process, what data to load, etc. Changes in read and write behavior and memory usage are also unpredictable. Therefore, if this information is collected as a random number seed, the generated random number is unpredictable.
  
  "/ Dev / random" can be used under Linux / Unix
  
  Under Windows, you can call the system's CryptGenRandom () function, which is mainly based on the current process Id, current thread Id, TickCount after system startup, current time, high-performance counter value returned by QueryPerformanceCounter, user name, computer name, CPU counter value, etc. Wait to calculate. Like "/ dev / random", the generation speed of CryptGenRandom () is relatively slow, and it consumes relatively large system resources.
  
  Of course, you can also use the RNGCryptoServiceProvider class (under the System.Security.Cryptography namespace) to generate true random numbers under .Net. According to a previous post on StackOverflow, RNGCryptoServiceProvider does not encapsulate the CryptGenRandom () function, but it is similar to the principle of CryptGenRandom () .
  
  8. Summary
  
  Some people may ask: Since there are "/ dev / random" and "true random number generators" like CryptGenRandom (), why do we need to provide and use "fake" like pseudo-random numbers? Because of the aforementioned "/ dev / random", CryptGenRandom () is slow to generate and consumes more performance. In cases where the unpredictability of random numbers is low, the pseudo-random number algorithm can be used because the performance is relatively high. For occasions where the unpredictability of random numbers is high, a true random number generator should be used. The hardware equipment of the true random number generator needs to consider cost issues, and "/ dev / random" and CryptGenRandom () have poor performance.
  
  Everything is perfect, there is no absolute good, and there is no absolute bad. This is the beauty of a diverse world.

Guess you like

Origin www.cnblogs.com/aquariusunny/p/12729910.html