Java Advanced-Multithreading

1. Talk about your understanding of programs, processes, threads

Procedure: A set of instructions written in a certain language to accomplish a specific task. It refers to a static code
process: it is a program execution process, a running program. As a unit of resource allocation
Thread: is an execution path within a program. As the smallest unit of scheduling and execution, each thread has an independent running stack and a program counter (pc)

2. Thread

Threads are the smallest unit of jvm scheduling, also known as lightweight processes. Processes are composed of threads. Threads have private program technology and stacks, and can access shared resources in the heap.

3. The creation of multiple threads

3.0 thread declaration cycle

New state:
After creating a thread object using the new keyword and the Thread class or its subclasses, the thread object is in a new state. It remains in this state until the program starts () this thread.

Ready state:
When the thread object calls the start () method, the thread enters the ready state. The thread in the ready state is in the ready queue, waiting to be scheduled by the thread scheduler in the JVM.

Running state:
If the thread in the ready state acquires CPU resources, you can execute run (), and the thread is now in the running state. The thread in the running state is the most complex. It can become blocked, ready, and dead.

Blocking state:
If a thread executes sleep, suspend and other methods, and after losing the occupied resources, the thread enters the blocking state from the running state. You can re-enter the ready state after the sleep time has expired or after obtaining device resources. Can be divided into three types:

Waiting for blocking: The thread in the running state executes the wait () method to make the thread enter the waiting for blocking state.

Synchronization blocking: The thread fails to acquire the synchronized lock (because the lock is occupied by other threads).

Other blocking: When an I / O request is issued by calling the thread's sleep () or join (), the thread will enter the blocking state. When the sleep () state times out, join () waits for the thread to terminate or time out, or the I / O processing is completed, and the thread re-enters the ready state

Dead state: When
a thread in a running state completes a task or other termination condition occurs, the thread switches to the termination state.Insert picture description here

3.1, inherited from the Thread class
  • 1. Create a subclass that inherits from the Thread class
  • 2. Rewrite Thread's run () —> Declare the operation performed by this thread in run ()
  • 3. Create objects of subclasses of Thread class
  • 4. Call start () through the object: ① start the current thread ② call the run () of the current thread
//1.创建一个继承于Thread类的子类
class MyThread extends Thread {
   //2.重写Thread的run()

   @Override
   public void run() {
       for (int i = 0; i < 100; i++) {
           if (i % 2 == 0) {
               System.out.println(Thread.currentThread().getName() + ":" + i);
           }
       }
   }
}


public class ThreadTest {
   public static void main(String[] args) {
//        3.创建Thread类的子类的对象
       MyThread t1 = new MyThread();
       //4.通过对象调用start()
       t1.start();
//        t1.run();错误的

       //如下方法任在主线程中进行的
       for (int i = 0; i < 100; i++) {
           if (i % 2 == 0) {
           //获取当前的线程名
               System.out.println(Thread.currentThread().getName() + ":" +i + "*************main()**********");
           }
       }
   }
}

3.2 Method 2: Implement Runnable interface
  • 1. Create a class that implements Runnable
  • 2. Implementation class to implement the abstract method of Runnnable, run ()
  • 3. Create an object that implements the class
  • 4. Pass this object as a parameter to the constructor of the Thread class to create an object of the Thread class
  • 5. Call start () through an object of class Thread
//1.创建一个实现了Runnable的类
class MThread implements Runnable {

   @Override
   public void run() {
       for (int i = 0; i < 100; i++) {
           if (i % 2 == 0) {
               System.out.println(Thread.currentThread().getName() + ":" + i);
           }
       }
   }
}

public class ThreadTest1 {
   //     3.创建实现类的对象
   public static void main(String[] args) {
       MThread mThread = new MThread();
       //4.将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
       Thread t1 = new Thread(mThread);
       t1.setName("线程1");
//        5.通过Thread类的对象调用start()①启动线程②调用当前线程的run();-->调用了Runnable类型的target
       t1.start();
       //在开启一个线程
       Thread t2 = new Thread(mThread);
       t2.setName("线程2");
       t2.start();
   }
}


3.3 Explain two issues:

Question 1: We start a thread, we must call the start () method, we cannot call the run () method to start the thread.
Question 2: If we start another thread, we must re-create an object of the Thread subclass and call the start () of this object )method

3.4 Common methods of Thread
  • 1.start (): Start the current thread, call the current thread's run ()

  • 2.run (): You usually need to override this method in the Thread class, and declare the operation to be performed by the created thread in this method

  • 3.currentThread (): Static method, returns the thread that executes the current code

  • 4.getName (): Get the name of the current thread

  • 5.setName (): Set the name of the current thread

  • 6. yield (): release the current CPU execution rights

  • 7.join (): In thread a, the join () method of thread b is called. At this time, thread a enters the blocked state, and thread a does not end the blocked state until thread b finishes executing.

  • 8.stop (): force to end the current thread, not recommended, outdated

  • 9.sleep (long millitime): Let the current thread sleep (block), specify the number of milliseconds, the current thread is blocked in the time of milliseconds

  • 1.isAlive (): judge whether the current thread is alive

  • Thread priority

  • MAX_PRIORITY:10

  • MIN_PRIORITY:1

  • NORM_PRIORITY: 5 default priority

  • 2. How to get and set the priority of the thread:

  • getPriority (): Get the priority of the thread

  • setPriority (int p): Set the priority of the thread

    说明:高优先级的线程要抢占低优先级的CPU的执行权,但是只是概率上来讲,高优先级的线程高概率下被执行,并不一定高优先级的线程执行完后,低优先级才执行
    
3.5 Example: Create three windows to buy tickets, the total number of tickets is 100, use Runable interface

class Window extends Thread implements  Runnable {
   private static int ticket = 100;
   Object obj = new Object();
   @Override
   public void run() {
       while (true) {
       //解决线程安全问题
           synchronized (obj){
               if (ticket > 0) {

                   try {
                       Thread.sleep(100);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }

                   System.out.println(Thread.currentThread().getName() + ":买票,票号为:" + ticket);
                   ticket--;
               } else {
                   break;
               }
           }
       }
   }

}

public class WindowTest {

   public static void main(String[] args) {
       Window w = new Window();

       Thread t1 = new Thread(w);
       Thread t2 = new Thread(w);
       Thread t3 = new Thread(w);
       t1.setName("窗口1");
       t2.setName("窗口2");
       t3.setName("窗口3");

       t1.start();
       t2.start();
       t3.start();
   }

}

The above operation has a thread safety problem, to be resolved

  • 1. In the process of buying tickets, there were heavy tickets and wrong tickets

  • 2. The cause of the problem: when a thread operates the ticket, the operation has not been completed yet, other threads participate and operate the ticket purchase

  • 3. How to solve: when a thread a is operating the ticket, other threads cannot participate, and the other threads do not participate until the thread a finishes operating the ticket

  • Can start to operate the ticket, even if the thread a is blocked, it cannot be changed

  • 4. Solve the problem of thread safety through the synchronization mechanism in java

  • Method 1: Synchronized code block (synchronized monitor) {

  • //需要被同步的代码
    
  • }
    Description: 1. The code for operating shared data is the code that needs to be synchronized

    2. Shared data: Variables operated by multiple threads

    3. Synchronous monitor: Commonly known as: lock. Objects of any class can act as locks

    Requirements: Multiple must share the same lock * Supplement: In the way of using Runable to create multi-threads, you can consider using this as a synchronization monitor

    In the way of creating threads using the Thread class, you should use this as a synchronization monitor carefully, you can consider using the current class as a synchronization monitor

Method 2: Synchronization method

If the code for operating shared data is fully declared in a method, we may wish to synchronize the method declaration.

5. The use of synchronous methods solves the problem of thread safety-benefits

When operating the synchronization code, only one thread participates, and the other threads wait, which is equivalent to a single-threaded process and is inefficient

Solve the thread safety problem three: lock lock-JDK5.0 new

3.6. Use the synchronization mechanism to rewrite the lazy style in singleton mode into thread-safe

1. Interview questions: What are the similarities and differences between synchronized and lock
*

  • The same point: solve the thread security problem
  • Different: the synchronized mechanism automatically releases the synchronization monitor after executing the corresponding synchronization code
  •  lock需要手动开启同步(lock()),同时结束同步也需要手动的实现(unlock());
    

* 2. Priority order: decreasing flexibility

  • lock lock-> synchronization code block (already entered the method body, allocated corresponding resources) ----> synchronization method (outside the method body)
  • Whether the lock still exists in the synchronization monitor, does not exist, lock is equivalent to the synchronization monitor
public class BankTest {
  private BankTest() {

  }

  private static BankTest instance = null;

  public static BankTest getInstance() {
      //方式一:效率稍差
//        synchronized (BankTest.class) {
//
//            if (instance == null) {
//                instance = new BankTest();
//            }
//            return instance;
//        }
      //方式二:效率更高
      if (instance == null){
          synchronized (BankTest.class){
              if (instance ==null){
                  instance = new BankTest();
              }
          }
      }
      return instance;
  }
}
3.7. Demo thread deadlock
  • 1. Understanding of deadlock: different threads occupy different resources required by each other and do not give up,

  • Are waiting for the other party to give up the synchronization resources they need, forming a thread deadlock

  • 2. Description:

  • After a deadlock occurs, there will be no exceptions or prompts, but all threads are blocked and cannot continue

public class ThreadTest {
   public static void main(String[] args) {

       StringBuffer s1 = new StringBuffer();
       StringBuffer s2 = new StringBuffer();


       new Thread() {
           @Override
           public void run() {
               synchronized (s1) {
                   s1.append("a");
                   s2.append("1");
                   try {
                       Thread.sleep(100);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }

                   synchronized (s2) {
                       s1.append("b");
                       s2.append("2");

                       System.out.println(s1);
                       System.out.println(s2);

                   }
               }

           }
       }.start();

       new Thread(new Runnable() {
           @Override
           public void run() {
               synchronized (s2) {
                   s1.append("c");
                   s2.append("3");
                   try {
                       Thread.sleep(100);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }

                   synchronized (s1) {
                       s1.append("d");
                       s2.append("4");

                       System.out.println(s1);
                       System.out.println(s2);

                   }
               }
           }
       }).start();
   }
}

4. Thread communication

Thread communication example: use two threads to print 1-100, thread 1 and thread 2, mutual printing

Three methods designed: can only appear in synchronized code blocks and synchronized methods

  • wait (): Once this method is executed, the current thread will enter the blocking state and release the synchronization monitor
  • notify (): Once this method is executed, it will wake up a thread blocked by wait, if there are multiple threads waiting, wake up the one with higher priority
  • notifyAll (): Once this method is executed, all threads blocked by beiwait will be awakened.
Explanation:

Note: 1. These three methods must be used in the synchronization code block and synchronization method
2. The caller of these three methods must be the synchronization code block or synchronization monitor in the synchronization method.
Otherwise, an exception error will occur
3. These three methods are defined in java.lang.Object

  • Synchronizing code blocks involves synchronizing monitors and sharing data,
  • synchronized (synchronous monitor) {
  • The code for operating data ensures that in the process of operating data, it is a single thread, and there will be no thread safety issues.
  • }
  • Data jointly manipulated by multiple threads: shared data, if another thread participates in a thread operation, there will be thread safety issues
Interview questions: similarities and differences between sleep and wait
  • The same point: Once the execution method can make the current thread enter the blocking state
  • Differences: 1. The positions of the two method declarations are different: sleep () is declared in the Thread class, and wait () is declared in the Object class
  • 2. The calling requirements are different: sleep () can be called in any required scenario. wait () can only be used in synchronized code blocks and synchronized methods
  • 3. The question about whether to release the synchronization monitor: if the two methods are used in the synchronization code block and synchronization method, sleep will not release the lock, wait () will
class Number implements  Runnable{
   private int number =1;

   @Override
   public void run() {
       while (true){
           synchronized (this) {
               //让线程进入就绪状态
               notify();

               if (number <= 100){
                   try {
                       Thread.sleep(10);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
                   System.out.println(Thread.currentThread().getName() +":" + number);
                   number++;

                   try {
                       //使得调用如下wait()方法的线程,进入阻塞状态
                       wait();
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }

               }else {
                   break;
               }
           }
       }
   }
}
public class CommunicationTest {
   public static void main(String[] args) {
       Number m1 = new Number();
       Thread t1 = new Thread(m1);
       Thread t2 = new Thread(m1);

       t1.setName("线程1");
       t2.setName("线程2");

       t1.start();
       t2.start();

   }
}

5. Three ways to create threads: implement Callable interface ---- JDK5.0 new

  • 1. Create an implementation class that implements the Callable interface
  • 2. Implement the call () method and declare the operation that this thread needs to perform in call ()
  • 3. Create an object of the Callable interface implementation class
  • 4. Pass the object of this callable implementation class to the FutureTask constructor to create an object of FutureTas
  • 5. Pass the object of FutureTask as a parameter to the constructor of the Thread class, create an object of the Thread class, and call the start () method
  • 6. Get the callable method in Callable as the return value
  • If you understand how to create a multi-thread by implementing the Callable interface is more powerful than the multi-thread by the Runnable interface?
  • 1.call () can have a return value
  • 2.call () can throw an exception and be caught by an outside operation to obtain the exception information
  • 3Callable supports generics
//1.创建一个实现Callable接口的实现类
class  NumThread implements Callable {
//2.实现call()方法,将此线程需要执行的操作声明在call()中
   @Override
   public Object call() throws Exception {
       int sum = 0;
       for (int i = 1; i <= 100; i++) {
           if (i % 2 == 0) {
               sum += i;
               System.out.println(i);
           }
       }
       return sum;
   }

}

public class ThreadNew {
   public static void main(String[] args) {
//        3.创建一个Callable接口实现类的对象
       NumThread numThread = new NumThread();
//        4.将此callable实现类的对象传递到FutureTask构造器中,创建FutureTas的对象
       FutureTask futureTask = new FutureTask(numThread);
//        5.将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread类的对象,调用start()方法
       new Thread(futureTask).start();

       try {
//            6.获取Callable中call的方法作为返回值
           //get()的返回值,即为FutureTask构造器参数Callable实现重写的call的返回值
           Object sum = futureTask.get();
           System.out.println("总和为:"+sum);
       } catch (InterruptedException e) {
           e.printStackTrace();
       } catch (ExecutionException e) {
           e.printStackTrace();
       }

   }
}

6. Four ways to create threads: use thread pool

benefit:

  • 1. Improve the response speed (reduced the time to create a new thread)
  • 2. Reduce resource consumption (reuse threads in the thread pool, do not need to be created every time)
  • 3. Easy thread management
  • corePoolsize: the size of the core pool
  • maximumPoolSize: maximum number of threads
  • keepAliveTime: How long to keep the thread before it terminates when it has no size
class NumberThread implements Runnable {

   @Override
   public void run() {
       for (int i = 0; i < 100; i++) {
           if (i % 2 == 0) {
               System.out.println(Thread.currentThread().getName() + ":" + i);
           }
       }
   }
}

public class ThreadPool {
   public static void main(String[] args) {
       //提供指定线程数量的线程池
       ExecutorService service = Executors.newFixedThreadPool(10);

       //设置线程池的属性
       System.out.println(service.getClass());
       //2.执行指定的线程操作/需要提供Runnable接口或Callable接口实现类的对象
       //        service.submit(Callable callable)//提交,适用于Callable接口
       service.execute(new NumberThread());//适用于Runnable接口
       //3.关闭线程池
       service.shutdown();
   }

}

Published 19 original articles · praised 0 · visits 492

Guess you like

Origin blog.csdn.net/weixin_43244120/article/details/105010437