Thread usage

Posted by cabaz777 on Sat, 01 Jan 2022 19:12:48 +0100

Thread creation and startup

The JVM of the Java language allows programs to run multiple threads through Java Lang. thread class.

Properties of Thread class

Each Thread completes its operation through the run() method of a specific Thread object. The body of the run() method is often called the Thread body

Start the Thread through the start() method of the Thread object instead of directly calling run()

Thread class

Constructor:

Thread(): creates a new thread object

Thread(String threadname): create a thread and specify the thread instance name

Thread(Runnable target): Specifies the target object to create the thread, which implements the run method in the Runnable interface

Thread(Runnable target, String name): creates a new thread object

Common methods:
  1.start(): Start the current thread and call the run()
  2.run():It usually needs to be rewritten Thread Class is declared in this method by the operation to be performed by the currently created thread
  3.currentThread():Static method that returns the thread executing the current code,stay Thread Subclass is this
  4.getName():Gets the name of the current thread
  5.setName():Sets the name of the current thread
  6.yield():Release current cpu Executive power of
  7.In thread a Calling thread b Medium join(),Thread at this time a It enters the blocking state until the thread b After full execution, the thread a To end the blocking state.
  8.stop():Obsolete. When this method is executed, the current thread is forced to end
 9.sleep(long millitime):Let the current thread"sleep"designated millitime Milliseconds at the specified millitime Within milliseconds, the current thread is blocked,
 10.isAlive():Determine whether the current thread is alive

Four ways to create threads

Method 1: inherit Thread class

1) Define subclasses that inherit the Thread class.

2) Override the run method in the Thread class in the subclass.

3) Create a Thread subclass object, that is, create a Thread object.

4) Call the thread object start method: start the thread and call the run method.

//1. Create a subclass inherited from Thread class
class MyThread extends Thread{
    //2. Override run() of Thread class
    @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. Create subclass objects of Thread class
        MyThread t1 = new MyThread();

        //4. Call start() through this object: ① start the current thread ② call run() of the current thread
          t1.start();
          //Problem 1: we can't start a thread by calling run() directly
//           t1.run();
        //Problem 2: start another thread and traverse the even number within 100. You can't let the thread that has started () execute. You need to re create one
//       t1.start();
        MyThread t2=new MyThread();
        t2.start();
         //The following operations are still performed in the main thread
        for(int i=0;i<100;i++){
            if(i%2==1){
                System.out.println(Thread.currentThread().getName()+":"+"*************************");
            }
        }

    }
}

Thread 1 and thread 2 run the rewritten run method, the main thread runs the program with * and the three threads run randomly

Note: 1 If you call the run() method manually, it is just a normal method and does not start the multithreading mode.

2. The run () method is called by the JVM. When it is called and the process control executed are determined by the CPU scheduling of the operating system.

3. To start multithreading, you must call the start method.

4. A thread object can only call the start() method once to start. If it is called repeatedly, the above exception "IllegalThreadStateException" will be thrown.

Method 2: implement Runnable interface

 1.Create an implementation runnable Class of interface
 2.Implementation class to implement Runnable Abstract methods in: run()
 3.Create an object that implements the class
 4.Pass this object as a parameter to Thread Class, create Thread Object of class
 5.adopt Thread Class start()
//1. Create a class that implements the runnable interface
class MThread implements Runnable{

    //2. Implement the class to implement the abstract method in Runnable: 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 ThreadTest1 {
    public static void main(String[] args) {
//        3. Create an object that implements the class
        MThread mThread = new MThread();
//        4. Pass this object as a parameter to the constructor of Thread class and create the object of Thread class
         Thread t1=new Thread(mThread);
//        5. Call start() through the object of Thread class: ① start the Thread ② call the run() of the current Thread --- > call the run() of the target of Runnable type
        t1.setName("Thread one");
        t1.start();

        //Start a thread and traverse even numbers within 100
        Thread t2=new Thread(mThread);
        t2.setName("Thread two");
        t2.start();
    }
}
Compare two ways to create threads:
  Implementation of priority principle in development Runaable Interface mode
 Reason: 1.The implementation method has no limitation of single inheritance of classes
      2.The implementation method is more suitable to deal with the situation that multiple threads share data
  Contact: public class Thread implements Runnable
  Same point: both methods need to be rewritten run(),Declare the logic to be executed by the thread in run()in

Method 3: implement Callable interface ------------- jdk5 0 NEW

How to understand implementation Callable Interface to create multithreading than implementation Runnable How powerful is the multithreading method of interface creation?
  1.call()There is a return value
  2.call()Exceptions can be thrown and captured by external operations to obtain exception information
  3.callable Support generics
//1. Create an implementation class that implements callable
class NumThread implements Callable {
     //2. Implement the call method and declare the operation to be executed by this thread in call()
    @Override
    public Object call() throws Exception {
        int sum=0;
        for(int i=0;i<=100;i++){
            if(i%2==0){
                System.out.println(i);
                sum+=i;
            }
        }
        return sum;
    }
}

public class ThreadTest3 {
    public static void main(String[] args) {
        //3. Create the object of the callable interface implementation class
        NumThread numThread = new NumThread();
        //4. Pass the object of this callable interface implementation class to the FutureTask constructor as an object to create the FutureTask object
        FutureTask futureTask = new FutureTask(numThread);
        //5. Pass the FutureTask object as a parameter to the constructor of the Thread class, create the Thread object, and call the start() method
        new Thread(futureTask).start();
        try {
            //6. Get the return value of call method in callable
            //The return value of get() is the FutureTask constructor parameter Callable. The implementation class overrides the method of call()
            Object sum=futureTask.get();
            System.out.println(sum);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

Future interface

You can cancel the execution results of specific Runnable and Callable tasks, query whether they are completed, obtain results, etc.

FutrueTask is the only implementation class of Futrue interface

FutureTask also implements Runnable and Future interfaces. It can be executed by the thread as Runnable or get the return value of Callable as Future

Four ways to create threads: using thread pool

Background: resources that are often created and destroyed and used heavily, such as threads in concurrency, have a great impact on performance.  idea: create many threads in advance, put them into the thread pool, obtain them directly when using them, and put them back into the pool after use. It can avoid frequent creation, destruction and reuse. Similar to public transport in life.

Benefits:

Improved response time (reduced time to create new threads)

Reduce resource consumption (reuse threads in the thread pool and do not need to be created every time)

Easy thread management

JDK 5.0 provides thread pool related API s: ExecutorService and Executors

ExecutorService: the real thread pool interface. Common subclass ThreadPoolExecutor

void execute(Runnable command): executes a task / command without a return value. It is generally used to execute Runnable

<T> Future<T> submit(Callable<T> task):  When executing a task, it has a return value and is generally executed again Callable 

void shutdown(): closes the connection pool

Executors: tool class and thread pool factory class, which are used to create and return different types of thread pools Newcachedthreadpool(): create a thread pool that can create new threads as needed newFixedThreadPool(n); Create a reusable thread pool with a fixed number of threads Newsinglethreadexecutor(): create a thread pool with only one thread Newscheduledthreadpool (n): creates a thread pool that can schedule commands to run after a given delay or execute periodically.

corePoolSize: the size of the core pool, maximumPoolSize: the maximum number of threads, keepAliveTime: the maximum time a thread can hold without a task, and then it will terminate

class NumberThread1 implements Runnable{
    @Override
    public void run() {
        for(int i=0;i<100;i++){
            if(i%2==0){
                System.out.println(Thread.currentThread().getName()+":"+i);
            }
        }
    }
}
class NumberThread2 implements Runnable{
    @Override
    public void run() {
        for(int i=0;i<100;i++){
            if(i%2==1){
                System.out.println(Thread.currentThread().getName()+":"+i);
            }
        }
    }
}
public class Threadpool {
    public static void main(String[] args) {
        //1. Provide a thread pool with a specified number of threads
        ExecutorService service = Executors.newFixedThreadPool(10);
        ThreadPoolExecutor service1=(ThreadPoolExecutor)service;
        //Set the properties of the thread pool
        System.out.println(service.getClass());//class java.util.concurrent.ThreadPoolExecutor
//        service1.setCorePoolSize(15);
//        service1.setKeepAliveTime(23);
        //2. To execute the operation of the specified thread, you need to provide an object that implements the Runnable or Callable implementation class
        service.execute(new NumberThread1());//Suitable for Runnable
        service.execute(new NumberThread2());
        //service.submit();// Suitable for use with callable
        //3. Close the connection pool
        service.shutdown();
    }
}

thread priority

Priority level of the thread

MAX_PRIORITY: 10

MIN _PRIORITY: 1

NORM_PRIORITY: 5

Methods involved

getPriority(): returns the thread priority value

setPriority(int newPriority): change the priority of the thread

Note: when a thread is created, it inherits the priority of the parent thread. A low priority only has a low probability of obtaining scheduling, and is not necessarily called after a high priority thread

Thread life cycle

New: when the object of a Thread class or its subclass is declared and created, the new Thread object is in the new state

Ready: after the thread in the new state is started (), it will enter the thread queue and wait for the CPU time slice. At this time, it has met the running conditions, but it has not been allocated CPU resources

Run: when the ready thread is scheduled and obtains CPU resources, it enters the running state. The run() method defines the operation and function of the thread

Blocking: in a special case, when the input / output operation is suspended or executed artificially, give up the CPU and temporarily suspend its execution to enter the blocking state

Death: the thread has completed all its work, or the thread is forcibly terminated in advance or ends with an exception

Thread synchronization

1. There is a security problem with multithreading

2. Cause of the problem: when multiple statements are operating on the same thread to share data, one thread only executes part of multiple statements, and another thread participates in the execution. The error that caused the shared data.

3. Solution: for multiple statements that share data, only one thread can complete the execution. During the execution, other threads cannot participate in the execution.

How to use Synchronized

1. Service environment

(1) Sync code block:

synchronized (object){

//Code to be synchronized;

}

(2) Synchronized can also be placed in the method declaration, indicating that the whole method is a synchronized method. For example:

public synchronized void show (String name){ .... }

2. What is the synchronized lock?

Any object can be used as a synchronization lock. All objects automatically contain a single lock (monitor).

Lock of synchronous method: static method (class name). Class), non static method (this)

Synchronous code block: you can specify it yourself, often as this or class name class

Note: it is very important to ensure that multiple threads using the same resource share the same lock. Otherwise, the safety of shared resources cannot be guaranteed. All static methods in a thread class share the same lock (class name). All non static methods share the same lock (this). Synchronize code blocks (be careful when specifying)

3. Scope of synchronization

(1) Identify which code is multithreaded

(2) Specify whether multiple threads share data

(3) Specify whether there are multiple statements operating on shared data in multithreaded running code

For statements with data shared by multiple operations, only one thread can complete the execution. During the execution, other threads cannot participate in the execution. That is, all these statements that operate on shared data should be placed in the synchronization range

Remember: the scope is too small: it does not lock all the code with security problems. The scope is too large: it does not play the function of multithreading.

4. Operation of releasing lock

The execution of the synchronization method and synchronization code block of the current thread ends.

The current thread encountered a break and return in the synchronization code block and synchronization method, which terminated the code block and continued execution of the method.

The current thread has an unhandled Error or Exception in the synchronization code block and synchronization method, resulting in an abnormal end

The current thread executes the wait() method of the thread object in the synchronization code block and synchronization method. The current thread pauses and releases the lock.

5. Operation without releasing the lock

When a thread executes a synchronous code block or synchronous method, the program calls thread sleep(), Thread. The yield () method pauses the execution of the current thread

When a thread executes a synchronous code block, other threads call the thread's suspend() method to suspend the thread, and the thread will not release the lock (synchronization monitor). Try to avoid using suspend() and resume() to control the thread

Lock (after JDK5.0)

class A{
    private final ReentrantLock lock = new ReenTrantLock();
    public void m(){
        lock.lock();
        try{
        //Thread safe code;
        }
        finally{
            lock.unlock(); 
        }
    }
}

Note: if there is an exception in the synchronization code, write unlock() to the finally statement block

Thread communication

wait():The thread enters a blocking state and releases the synchronization monitor
notify():Once executed, it will be awakened wait If more than one thread is wait,Will wake up the high priority
notifyAll():Once executed, it will wake up all the victims wait Process of

Note: these three methods can only be used in the synchronized method or synchronized code block, otherwise they will report Java Lang.illegalmonitorstateexception exception.

Because these three methods must be called by a lock Object, and any Object can be used as a synchronized lock, these three methods can only be declared in the Object class.

Case: use two threads to print 1-100, thread 1 and thread 2 to print alternately

class Number implements Runnable{
    private int number=1;
    private  Object obj=new Object();
    @Override
    public void run() {
        while(true){
            synchronized (obj) {

               obj.notifyAll();

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

                    try {
                        //Make the thread calling the following wait() method enter the blocking state
                        obj.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

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

        t1.setName("Thread 1");
        t2.setName("Thread 2");

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