头图

process and thread

  • A process is the basic unit for a program to request resources (such as memory space and file handles) from the operating system.
  • A thread is the smallest unit in a process that can execute independently.

JAVA thread API

  1. To create a thread in Java is to create an instance of the Thread class.
  2. Each thread has its own task to execute. The processing logic of the thread task is implemented or called in the run method of the Thread class, so the run method is equivalent to the entry method of the thread task logic processing, which is run by the java virtual machine The corresponding thread is called, not by the application code.
  3. The start method of the Thread class is used to start related threads. The essence of starting a thread is to request the java virtual machine to run the corresponding thread, and when the thread runs is determined by the thread scheduler. Therefore, although the start method is executed , but it does not mean that the thread starts running, it may run later, or it may never run.
  4. The two commonly used constructors in Thread are: Thread() and Thread(Runnable target). These two methods of creating threads are as follows:

    1. Create a thread by defining a subclass of the Thread class

       public class WelcomeApp {
      
        public static void main(String[] args) {
          // 创建线程
          Thread welcomeThread = new WelcomeThread();
      
          // 启动线程
          welcomeThread.start();
      
          // 输出“当前线程”的线程名称
          System.out.printf("1.Welcome! I'm %s.%n", Thread.currentThread().getName());
        }
      }
      
      // 定义Thread类的子类
      class WelcomeThread extends Thread {
      
        // 在该方法中实现线程的任务处理逻辑
        @Override
        public void run() {
          System.out.printf("2.Welcome! I'm %s.%n", Thread.currentThread().getName());
        }
      }
    2. Create a thread by implementing the Runnable interface

       public class WelcomeApp1 {
      
        public static void main(String[] args) {
          // 创建线程
          Thread welcomeThread = new Thread(new WelcomeTask());
      
          // 启动线程
          welcomeThread.start();
          // 输出“当前线程”的线程名称
          System.out.printf("1.Welcome! I'm %s.%n", Thread.currentThread().getName());
      
        }
      
      }
      
      class WelcomeTask implements Runnable {
        // 在该方法中实现线程的任务处理逻辑
        @Override
        public void run() {
          // 输出“当前线程”的线程名称
          System.out.printf("2.Welcome! I'm %s.%n", Thread.currentThread().getName());
        }
      
      }
  5. No matter which of the above methods is used to run, once the execution of the run method of the thread ends, the running of the corresponding thread ends, and the resources occupied by the thread that ends will be garbage collected by the Java virtual machine like other Java objects.
  6. An instance of Thread can only be started once. If an instance of start() is called multiple times, it will throw a IllegalThreadStateException exception.
  7. You can get the current thread through Thread.currentThread(), and then you can set properties on it or get its related information, for example:

     Thread.currentThread().setName("线程A");
    Thread.currentThread().getName();
  8. In the above, the run method of the thread is generally called by the java virtual machine, but the thread is also an instance of the Thread class. Secondly, the run method is also modified by the public modifier, so the run method can also be called directly, but it is generally not done. Against the original intent of our bed frame thread.

     public class WelcomeApp {
    
      public static void main(String[] args) {
        // 创建线程
        Thread welcomeThread = new WelcomeThread();
        // 启动线程
        welcomeThread.start();
        // 输出“当前线程”的线程名称
        System.out.printf("1.Welcome! I'm %s.%n", Thread.currentThread().getName());
        welcomeThread.run();
      }
    }
    
    // 定义Thread类的子类
    class WelcomeThread extends Thread {
    
      // 在该方法中实现线程的任务处理逻辑
      @Override
      public void run() {
        System.out.printf("2.Welcome! I'm %s.%n", Thread.currentThread().getName());
      }
    }
    ==================结果==================
    1.Welcome! I'm main.
    2.Welcome! I'm Thread-0.
    2.Welcome! I'm main.
  9. properties of the thread

    Attributes Property Type and Purpose read only Important Notes
    Numbering
    ID
    Used to identify different threads, different threads have different numbers Yes After a thread with a certain number has finished running, that number may be used by subsequent threads that are created. Although the numbers owned by different threads are different, the uniqueness of this number is only valid in one operation of the Java virtual machine. That is to say, after restarting a Java virtual machine (such as restarting a web server), the number of some threads may be the same as the number of a thread that was run by the Java virtual machine last time, so the value of this property is not suitable for use as a unique identifier , especially as a unique identifier in the database (like a primary key)
    name
    Name
    Used to distinguish different threads. The default value is related to the thread number. The format of the default value is: Thread-thread number, such as Thread-0 no Java does not forbid us to set the name property of different threads to the same value. Nonetheless, setting the thread's name property can help with code debugging and problem localization
    thread class
    Daemon
    A value of true indicates that the corresponding thread is a daemon thread, otherwise it indicates that the corresponding thread is a user thread. The default value of this property is the same as the value of the property of the parent thread of the corresponding thread. When a java program is stopped normally, when a user thread has not finished executing, the virtual machine will not stop immediately, and will wait for its execution to complete, but if only the guard If the thread has not finished executing, it will not prevent the virtual machine from stopping, which means that the daemon thread is usually used to perform some tasks that are not very important, such as monitoring the execution of other threads. no This property must be set before the corresponding thread is started, that is, the call to the setDaemon method must precede the call to the start method, otherwise the setDaemon method will throw an IllegalThreadStateException. Threads responsible for some critical tasks are not suitable to be set as daemon threads
    priority
    Priority
    This property is essentially a hint to the thread scheduler to indicate which thread the application wants to run first. Java defines 10 priority levels from 1 to 10. The default value is generally 5. For a specific thread, the default value of its priority is equal to the priority value of its parent thread (the thread that created the thread). no Generally, the default priority can be used. Improperly setting this property value can cause serious problems (thread starvation)
  10. thread method

    method Features Remark
    static Thread
    currentThread()
    Returns the current thread, the execution thread (object) of the current code The same piece of code calls Thread.currentThread(), and its return value may correspond to different threads (objects)
    void run() Task processing logic for implementing threads This method is called directly by the Java virtual machine, and in general applications should not call this method
    void start() start the corresponding thread The return of this method does not mean that the corresponding thread has been started. The start method of a Thread instance can only be called once, and multiple calls will cause an exception to be thrown
    void join() Wait for the corresponding thread to finish running If thread A calls the join method of thread B, the running of thread A will be suspended until thread B finishes running
    static void yield() Causes the current thread to voluntarily relinquish its occupancy of the processor, which may cause the current thread to be suspended This method is unreliable. The current thread may continue to run when this method is called (depending on the current health of the system)
    static void sleep(long millis) Sleeps (suspends) the current thread for the specified time

The relationship between Thread and Runnable

  1. The Thread class implements the Runnable interface

     public class Thread implements Runnable{}
  2. Runnable is an interface and there is only one method in it, so the class that implements Runnable needs to rerun the method.
  3. The process of executing the task logic in two ways

    • Implement the Runnable interface and override the run method

       class WelcomeTask implements Runnable {
        @Override
        public void run() {
          //任务逻辑 
        }
      }
       new Thread(new WelcomeTask()).start();

      WelcomeTask In the process of passing the instance in Thread, it will eventually be assigned to a target member variable in Thread

       private Runnable target;

      The specific process is as follows:
      1. There is a constructor with parameters to generate a ThreadName, for example: Thread-0

       public Thread(Runnable target) {
          init(null, target, "Thread-" + nextThreadNum(), 0);
      }

      2. Enter the first initialization function, there is no need to pay attention to other parameters, because there are other construction methods that will call init(...)

       private void init(ThreadGroup g, Runnable target, String name,long stackSize){
          init(g, target, name, stackSize, null, true);
      }

      3. The second layer initialization function, that is to assign the target

       private void init(ThreadGroup g, Runnable target, String name,
                        long stackSize, AccessControlContext acc,
                        boolean inheritThreadLocals) {
          if (name == null) {
              throw new NullPointerException("name cannot be null");
          }
      
          this.name = name;
          .....
          this.target = target;
          ....
      }

      4. The Thread instance calls the start() method

       public synchronized void start() {
          //threadStatus != 0代表这个Thread实例已经被start()过了,所以会抛出异常
          if (threadStatus != 0)
              throw new IllegalThreadStateException();
          ...
          try {
              //最终会调用本地方法start0()来启动这个线程
              start0();
              ...
          } finally {
              ...
          }
      }

      5. The native method starts the thread, that is, the thread is handed over to the thread scheduler of the virtual machine

       private native void start0();

      6. The thread scheduler executes the thread task logic

       //启动线程后,调度器会帮助我们运行执行线程run()方法,即任务逻辑
      //如果target != null的时候会调用WelcomeTask中实现的任务逻辑,否则什么都不会执行
      public void run() {
          if (target != null) {
              target.run();
          }
      }
    • Inherit the Thread class and override the run method

       class WelcomeThread extends Thread {
           @Override
           public void run() {
             //任务逻辑
           }
      }
       new WelcomeThread().start();
      ...
      //任务调度器直接调用WelcomeThread中实现的任务逻辑
  4. The difference between the two ways

    • Object-oriented perspective: one is based on inheritance implementation extends Thread , and the other is based on composition new Thread(new Runable()) , composition is less coupled than inheritance.
    • The perspective of object sharing: a CountingTask instance can be shared by multiple threads so there may be resource contention problems.

       class CountingThread extends Thread {
          int count = 0;
          @Override
          public void run() {
              for (int i = 0; i < 100; i++) {
                  i++;
              }
          }
          System.out.println("count:" + count);
      }
      
      class CountingTask implments Runnable {
          int count = 0;
          @Override
          public void run() {
              for (int i = 0; i < 100; i++) {
                  i++;
              }
          }
          System.out.println("count:" + count);
      }
      
      public static void main(String[] args) {
          Thread thread;
          CountingTask task = new CountingTask();
          for(int i = 0;i < 10;i++){
              thread = new Thread(task);
              thread.start();
          }
          for(int i = 0;i < 10;i++){
              thread = new CountingThread();
              thread.start();
          }
      }

thread life cycle

  1. New
    Thread thread = new Thread();
    At this point, the thread just prepares for new and does not start executing.
  2. Runnable
    thread.start();
    1.ready: The resource has not been allocated yet.
    2.running: is executing.
  3. block
    1.Blocked does not acquire the lock of the synchronized protected code.
    2.Waiting (waiting)

     1.Object.wait(); 
         - o.notify()/o.notifyAll()
     2.Thread.join(); 
         - join线程结束/被中断 
     Blocked与Waiting的区别是Blocked是在等待释放某个资源,Waiting是在等待达到某个条件 。
  4. Time Waiting Some blocking with time parameters set.
    1.Thread.sleep(m);

     - 时间超时/join的进程结束/被中断 。

    2.Object.wait(m)

     - 时间到/o.notify()/o.notifyAll()

    3.Thread.join(m)

     - 时间超时/join的进程结束/被中断 。
  5. Terminated
    1. The run method is executed normally.
    2. An uncaught exception occurred and terminated unexpectedly.

eacape
205 声望8 粉丝

JAVA 攻城狮