Basic Learning tutorials for thread classes in Java threading programming _java

Source: Internet
Author: User
Tags thread class

A. The state of a thread

Before you formally learn the specific methods in the thread class, let's take a look at the state of the thread, which will help you to understand the methods in the thread class later.

Threads from creation to eventual extinction, go through a number of States. In general, threads include the following states: Creation (new), Ready (runnable), running (running), blocking (blocked), time waiting, waiting, extinction (dead).

When a new thread is needed to perform a child task, a thread is created. However, after the thread is created, it is not immediately ready, because the thread's operation requires some conditions (such as memory resources, in the previous JVM memory area to divide a posting know that the program counter, Java stack, local method stack are thread-private, so need to allocate a certain amount of memory space for the thread) Only when all the conditions required for the thread to run are satisfied, will the ready state be entered.

When the thread is in a ready state, it does not mean that the CPU execution time is immediately available, and perhaps the CPU is performing something else at this time, so it waits. When the CPU execution time is obtained, the thread actually enters the running state.

Thread in the running state, there may be several reasons for the current thread does not continue to run, such as the user actively let the thread sleep (after a certain amount of time after sleep), the user actively let the thread wait, or be blocked by the synchronized block, which corresponds to a number of states: Time Waiting (sleep or wait for certain events), waiting (waiting to be awakened), blocked (blocking).

When a sudden interruption or a subtask completes, the thread will die out.

The following diagram depicts the state of a thread from creation to extinction:

In some tutorials, blocked, waiting, time waiting are collectively called blocking states, which is OK, except that I want to link the state of the thread to the method call in Java, so the waiting and time waiting two states are separated.

Two. Context switching

For a single core CPU (for multi-core CPUs, this is understood as a kernel), the CPU can only run one thread at a time, when the process of running a thread to run another thread, this is called the thread context switch (similar to the process).

Because it is possible that the task of the thread is not finished, you need to save the running state of the threads at the time of the switch so that you can continue to run before switching back again. As a simple example: a thread A is reading the contents of a file, reading half of the file, you need to suspend thread A, go to execute thread B, and when you switch back to execute thread a again, we don't want thread A to read from the beginning of the file.

So you need to record the running state of thread A, so what data do you record? Because the next time you recover, you need to know which instruction the current thread has executed before. So you need to record the value of the program counter, in addition to the thread is in the calculation of the time is suspended, so the next time to continue the execution of the time required to know the value of the variable before the number, so you need to record the state of the CPU registers. Therefore, in general, the thread context switching process will record the program counter, CPU register state and other data.

To put it simply: the context switch for a thread is actually the process of storing and recovering the CPU state, which enables the thread execution to resume execution from the breakpoint.

Although multithreading can improve the efficiency of task execution, you should pay attention to these factors when multithreaded programming due to the same overhead costs associated with thread switching, and multiple threads that can lead to increased system resource consumption.

Three. Methods in the Thread class

By looking at the source of the Java.lang.Thread class:

The thread class implements the Runnable interface, and in the thread class, there are some of the more critical attributes, such as name, the thread name, which can be specified by the parameters in the constructor of the thread class. Priority represents the priority of a thread (the maximum is 10, the minimum value is 1, the default is 5), and daemon indicates whether the thread is a daemon, and target represents the task to perform.

The following methods are commonly used in the thread class:

Here are a few ways to relate to the running state of a thread:

1) Start method

Start () is used to start a thread, and when the Start method is invoked, the system opens a new thread to perform user-defined subtasks, in which resources are allocated for the appropriate thread.

2) Run method

The run () method does not require a user to invoke, and when a thread is started through the Start method, when the thread obtains the CPU execution time, it enters the Run method body to perform the specific task. Note that the inheritance thread class must override the Run method to define the specific task to perform in the Run method.

3) Sleep method

The sleep method has two overloaded versions:


Sleep (long Millis)   //parameter is millisecond sleep
 
(long millis,int nanoseconds)  //First parameter is millisecond, second parameter is nanosecond

Sleep is the equivalent of getting the thread asleep, handing over the CPU and letting the CPU perform other tasks.

However, it is important to note that the sleep method does not release the lock, which means that if the current thread holds a lock on an object, other threads cannot access the object even if the sleep method is invoked. See the following example to make it clear:


public class Test {
   
  private int i = ten;
  Private object = new Object ();
   
  public static void Main (string[] args) throws IOException {
    test test = new test ();
    Mythread thread1 = Test.new mythread ();
    Mythread thread2 = Test.new mythread ();
    Thread1.start ();
    Thread2.start ();
  } 
   
   
  Class Mythread extends thread{
    @Override public
    void Run () {
      synchronized (object) {
        i++;
        System.out.println ("I:" +i);
        try {
          System.out.println ("Thread" +thread.currentthread (). GetName () + "Enter sleep state");
          Thread.CurrentThread (). Sleep (10000);
        catch (Interruptedexception e) {
          //Todo:handle exception
        }
        System.out.println ("thread" + Thread.CurrentThread (). GetName () + "End of Sleep");
        i++;
        System.out.println ("I:" +i);}}}

Output results:

From the above output, it can be seen that when the Thread-0 into the sleep state, Thread-1 did not go to perform specific tasks. Only when the Thread-0 is finished, the THREAD-0 releases the object lock and Thread-1 begins execution.

Note that if you call the Sleep method, you must catch the interruptedexception exception or throw the exception to the upper level. When a thread is full of sleep time, it does not necessarily occur immediately because the CPU may be performing other tasks at this time. So calling the sleep method is equivalent to getting the thread into a blocking state.

4) Yield method

Invoking the yield method allows the current thread to hand over CPU permissions, allowing the CPU to execute other threads. It is similar to the sleep method and does not release locks. However, yield cannot control the specific time to hand over the CPU, and the yield method only allows threads with the same priority to have access to CPU execution time.

Note that calling the yield method does not leave the thread in a blocking state, but rather the thread is back to the ready state, and it only needs to wait for the CPU execution time to be retrieved, which is not the same as the sleep method.

5) Join method

The Join method has three overloaded versions:

Join ()
join (long Millis)   //parameter is a MS
join (long millis,int nanoseconds)  //The first parameter is milliseconds, the second parameter is nanosecond

If you call the Thread.Join method in the main thread, the main method waits for the thread thread to finish or wait for a certain amount of time. If you call a parameterless join method, wait for thread execution to complete, and wait for a certain event if you call a join method that specifies a time parameter.

Look at one of the following examples:

public class Test {public
   
  static void Main (string[] args) throws IOException {
    System.out.println ("Enter Thread" +thread . CurrentThread (). GetName ());
    Test test = new test ();
    Mythread thread1 = Test.new mythread ();
    Thread1.start ();
    try {
      System.out.println ("Thread" +thread.currentthread (). GetName () + "Wait");
      Thread1.join ();
      SYSTEM.OUT.PRINTLN ("Thread" +thread.currentthread (). GetName () + "continue execution");
    catch (Interruptedexception e) {
      //TODO auto-generated catch block
      e.printstacktrace ();
    }
  } 
   
  Class Mythread extends thread{
    @Override public
    void Run () {
      System.out.println ("Enter thread" + Thread.CurrentThread (). GetName ());
      try {
        thread.currentthread (). Sleep (5000);
      } catch (Interruptedexception e) {
        //Todo:handle exception< c23/>}
      System.out.println (thread +thread.currentthread (). GetName () + execution complete);}}

Output results:

 

As you can see, when the Thread1.join () method is invoked, the main thread enters the wait and waits for Thread1 to execute before continuing.

In fact, calling the Join method calls the object's Wait method, which can be seen by looking at the source:

  

The wait method will cause the thread to go into a blocking state and release the thread-occupied locks and hand over the CPU execution permissions.

Because the wait method lets the thread release the object lock, the Join method also lets the thread release the lock held on an object. The specific wait method is used in the following article.

6) Interrupt Method

Interrupt, as the name suggests, is the meaning of interruption. Calling the interrupt method individually can cause a blocked thread to throw an exception, which means it can be used to break a thread that is in a blocking state, and to stop a running thread through the interrupt method and the Isinterrupted () method.

Let's look at an example:

public class Test {public
   
  static void Main (string[] args) throws IOException {
    test test = new test ();
    Mythread thread = Test.new mythread ();
    Thread.Start ();
    try {
      thread.currentthread (). Sleep (=),
    catch (Interruptedexception e) {
       
    }
    thread.interrupt ();
  } 
   
  class Mythread extends thread{
    @Override public
    void Run () {
      try {
        System.out.println (" into a state of sleep ");
        Thread.CurrentThread (). Sleep (10000);
        SYSTEM.OUT.PRINTLN ("complete Sleep");
      } catch (Interruptedexception e) {
        System.out.println ("Get interrupt Exception");
      }
      System.out.println ("Run Method execution completed");}}

Output results:

It can be seen from here that the blocking thread can be interrupted by the interrupt method. Can you interrupt a thread that is not blocked? Look at the following example:

public class Test {public
   
  static void Main (string[] args) throws IOException {
    test test = new test ();
    Mythread thread = Test.new mythread ();
    Thread.Start ();
    try {
      thread.currentthread (). Sleep (=),
    catch (Interruptedexception e) {
       
    }
    thread.interrupt ();
  } 
   
  class Mythread extends thread{
    @Override public
    void Run () {
      int i = 0;
      while (I<integer.max_value) {
        System.out.println (i+ "while loop");
        i++}}}}

Running the program will find that the while loop runs until the value of the variable I exceeds integer.max_value. So the direct call to the interrupt method does not interrupt the thread that is running.

However, if you can interrupt a running thread with isinterrupted (), because calling the interrupt method is equivalent to using the interrupt flag position to be true, you can determine whether the interrupt flag is executed by calling isinterrupted () by invoking the bit. For example, the following code:

public class Test {public
   
  static void Main (string[] args) throws IOException {
    test test = new test ();
    Mythread thread = Test.new mythread ();
    Thread.Start ();
    try {
      thread.currentthread (). Sleep (=),
    catch (Interruptedexception e) {
       
    }
    thread.interrupt ();
  } 
   
  class Mythread extends thread{
    @Override public
    void Run () {
      int i = 0;
      while (!isinterrupted () && i<integer.max_value) {
        System.out.println (i+ "while loop");
        i++}}}}

The run will find that after printing several values, the while loop stops printing.

In general, however, it is not recommended to break a thread in this way, typically adding a property isstop to the Mythread class to flag whether to end a while loop and then to judge the value of isstop in the while loop.

Class Mythread extends thread{
    private volatile Boolean isstop = false;
    @Override public
    Void Run () {
      int i = 0;
      while (!isstop) {
        i++
      }
    }
     
    public void Setstop (Boolean stop) {
      this.isstop = stop;
    }
  }

You can then terminate the while loop outside by calling the Setstop method.

7) Stop method

The Stop method is already an obsolete method, and it is an unsafe method. Because calling the Stop method terminates the call to the Run method directly, and throws a Threaddeath error, if the thread holds an object lock, the lock is completely freed, causing the object state to be inconsistent. So the Stop method is basically not going to be used.

8) Destroy method

The Destroy method is also an obsolete method. Basically will not be used to.

Here are a few ways to relate to threading properties:

1) getId

Used to get the thread ID

2) GetName and SetName

Used to get or set the thread name.

3) GetPriority and SetPriority

Used to get and set the thread priority.

4) Setdaemon and Isdaemon

Used to set whether a thread becomes a daemon and determines whether the thread is a daemon thread.

The difference between a daemon thread and a user thread is that the daemon relies on the thread that created it, and the user thread is not dependent. As a simple example: if you create a daemon thread in the main thread, when the main method is finished running, the daemon thread will die. The user thread does not, and the user thread runs until it has finished running. In the JVM, a thread like a garbage collector is a daemon.

The thread class has a more commonly used static method CurrentThread () to get the current thread.

With most of the methods in the thread class mentioned above, how does a method call in the thread class cause the thread state to change? The following diagram is an improvement on the diagram above:

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.