Java multi-threaded super detailed to the extreme content!

1. Thread overview

1.1 threads and processes

  • A process is a program in the running process, and has a certain independent function
  • Concurrency : Only one instruction can be executed at the same time, but multiple process instructions are executed in rapid rotation
  • Parallel : multiple instructions are executed simultaneously on multiple processors
  • The thread is the execution unit of the process

1.2 Advantages of multithreading

  • Memory cannot be shared between processes, but it is very easy between threads
  • When the system creates a process, it needs to reallocate system resources for the process, but the cost of creating threads is much smaller, so it is more efficient to use multithreading
  • Java language has built-in multi-threading function

2. Thread creation and startup

2.1 Inherit Thread

public class FirstThread extends Thread {
    private int i;

    @Override
    public void run() {
        for(i = 0; i < 50; i ++){
            System.out.println(this.getName() + "" + i);
        }
    }

    public static void main(String[] args){
        FirstThread ft = new FirstThread();
        for(int i =0; i < 100;i ++){
            System.out.println(Thread.currentThread().getName() + "" + i);
            if(i == 20) {
                ft.run();
            }
        }
    }
}

2.2 Implement Runnable interface

public class FirstThread implements java.lang.Runnable {
    private int i;

    public void run() {
        for(i = 0; i < 50; i ++){
            System.out.println(Thread.currentThread().getName()+ "" + i);
        }
    }

    public static void main(String[] args){
        FirstThread ft = new FirstThread();
        for(int i =0; i < 100;i ++){
            System.out.println(Thread.currentThread().getName() + "" + i);
            if(i == 20) {
                ft.run();
            }
        }
    }
}

2.3 Use Callable and Future

  • CallableThe interface provides a call()method that can be used as a thread execution body, the call()method has a return value and can declare to throw an exception
  • Java5 provides an Futureinterface to represent the return value Callableof the call()method in the Futureinterface , and provides an FutureTaskimplementation class for the interface
  • FutureMethod of interface definition:
Method name effect
boolean cancel(boolean mayInterruptIfRunning) Attempt to cancel the task Futureassociated thereCallable
V get() Return the return value of the method in the Callabletask. callThis method will cause the thread to block, and it will be obtained after the child thread is executed.
V get(long timeout, TimeUnit unit) Return the return value Callableof the callmethod in the task . This method allows the program to block at most timeoutand the unitspecified time, and if the Callabletask has not returned a value after the specified time, TimeoutExceptionan exception is thrown
boolean isCancelled() CallableWhether the task in is cancelled
boolean isDone() CallableWhether the task in is completed
public class CallableDemo {
    public static void main(String[] args){
        FutureTask<Integer> task = new FutureTask<Integer>((Callable<Integer>)() -> {
            int i = 0;
            for( ; i < 100; i++){
                System.out.println(i);
            }
            return i;
        });
        new Thread(task).start();
        try {
            System.out.println(task.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

2.4 Comparison of three ways to create threads

RunnableAnd Callableadvantages and disadvantages:

  • Thread class implements only Runnable, Callablethe interface, you can inherit from other classes
  • In the case of Runnable and Callable, multiple threads can share the same targetobject, so it is very suitable for multiple same threads to process the same resource
  • Programming is slightly more complicated, if you need to access the current thread, you must useThread.currentThread()

ThreadAdvantages and Disadvantages:

  • The thread class has inherited the Threadclass, so it can no longer inherit from other parent classes
  • Simple to write, if you need to access the current thread, thisuse

3. Thread life cycle

3.1 New and ready state

  • newThe statement is only allocated memory by the Java virtual machine, and it does not show any dynamic characteristics of threads
  • If you directly call the runmethod of the inherited class , there will only be MainActivity, and you cannot getNameget the name of the current execution thread, but need to useThread.currentThread().getName()
  • After calling the runmethod, the thread is no longer in the newly created state

3.2 Running and blocking state

  • When the number of threads is greater than the number of processors, there are multiple threads rotating on the same CPU
  • Cooperative scheduling strategy : Only when a thread calls the sleep()OR yield()method will it give up the occupied resources-that is, the thread must actively give up the occupied resources
  • Preemptive scheduling strategy : The system allocates a small period of time to each executable thread to process the task. When the task is completed, the system will deprive the thread of resources occupied
  • The blocked thread will re-enter the ready state when appropriate

image

3.3 State of death

  • Test thread death availableisAlive()
  • The thread that is dead cannot run again, otherwise IllegalThreadStateExceptionan exception will be thrown

4. Control thread

4.1 join thread

  • In the MainActivitycall A.join(), it MainActivityis blocked, A thread of execution after MainActivityit executed

4.2 Daemon Thread

  • If all foreground threads die, background threads will die automatically
public class DaemonThread extends Thread {
    @Override
    public void run() {
        for(int i = 0; i< 1000; i++){
            System.out.println("DaemonActivity" + i);
        }
    }

    public static void main(String[] args){
        DaemonThread thread = new DaemonThread();
        thread.setDaemon(true);
        thread.start();
        for(int i = 0; i < 10; i ++ ){
            System.out.println("MainActivity" + i);
        }
    }
}

image

4.3 thread sleep sleep

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

  • sleepAfter the method suspends the current thread, it will give other threads a chance to execute, and ignore the priority of other threads; but the yieldmethod will only give threads with the same or higher priority
  • sleepThe method will turn into the blocking state, and will not turn into the ready state until the blocking time has passed; yieldforce the current thread into the ready state
  • sleepThe method throws InterruptedException, the yield method does not throw an exception

4.4 Change thread priority

  • Threads with high priority get more execution opportunities, threads with low priority get fewer execution opportunities
  • setPriorityAnd getPrioritymethods to set and return the priority of the specified thread

5. Thread synchronization

  • run()Method does not have synchronization security
  • ***java*** introduces a synchronization monitor to solve the problem of multi-thread synchronization, sychronized(obj)which objmeans sharing resources

5.1 Synchronization method

  • Synchronous method is to use synchronizedto modify a method
  • The default synchronization monitor for instance methods isthis
  • The immutable classes in ***Java*** are always thread-safe, and mutable objects need additional methods to ensure their thread safety
public class DaemonThread extends Thread {

    static int balance = 100;
    int drawAmount;
    String name;

    public DaemonThread(int drawAmount, String name){
        this.drawAmount = drawAmount;
        this.name = name;
    }

    @Override
    public void run() {
        this.draw(drawAmount);
    }

    public synchronized void draw(int amount){
        if(balance  >= amount){
            System.out.println(this.name + "取出了" + amount);
            try{
                Thread.sleep(1);
            } catch (InterruptedException e){
                e.printStackTrace();
            }
            balance -= amount;
            System.out.println("\t余额为" + balance);

        } else{
            System.out.println(this.name + "取现失败");
        }
    }
    public static void main(String[] args){
        new DaemonThread(50, "A").start();
        new DaemonThread(100, "B").start();
    }
}

5.2 Release the lock of the synchronization monitor

In the following cases, the thread will release the lock on the synchronization monitor

  • The synchronization method of the current thread, the synchronization code block execution ends
  • Encountered break , return
  • Encountered an exception
  • The program executed the wait()method to synchronize the monitor object

Will not be released under the following circumstances:

  • When executing a synchronous method, the program calls the Thread.sleep() Thread.yield()method
  • Another thread called the thread's suspendmethod

5.3 Synchronization lock

  • ***Java5*** provides a more powerful synchronization lock mechanism, which can be synchronized by explicitly defining synchronization lock objects
  • Lock provides a wider range of locking operations than synchronized, and supports multiple related Condition objects
  • Lock type:
    Lock
    ReadWriteLock
    ReentrantLock : commonly used, you can relock a locked object
    ReentrantReadWriteLock
    StampedLock
Method name effect
lock Lock
unlock Unlock

5.4 Deadlock

A and B, B and A

5.5 Thread communication

5.5.1 Traditional thread communication

Method name effect
wait Cause the current thread to wait until other threads call the notify()or notifyAll()method of the synchronization monitor
notify Wake up a single thread waiting in this synchronization monitor
notifyAll Wake up all threads waiting in this synchronization monitor
  • wait()Must be executed with lock

5.5.2 Using Condition

  • If not applicable synchronized system to ensure thread synchronization, using Lock objects to ensure synchronization, it can not be used wait, notify, notifyAll()to thread communication
  • When using Lockobjects, Java provides Conditionguaranteed thread coordination
  • ConditionMethods as below
Method name effect
await Cause the current thread to wait until other threads call the signal()or signalAll()method of the synchronization monitor
signal Wake up a single thread in this Lock object
signalAll Wake up all threads in this Lock object

5.5.3 Using a blocking queue

  • ***Java*** provides a BlockingQueue interface
  • When the producer thread tries to BlockingQueueput elements in, if the queue is full, the thread is blocked; when the consumer thread tries to BlockingQueuetake out elements, if the queue is empty, the thread is blocked
Method name effect
put(E e) Try to put the E element intoBlockingQueue
take() Try to BlockingQueueextract elements from the head of
public class BlockingQueueThread extends Thread {

    private BlockingQueue<String> bq;

    public BlockingQueueThread(BlockingQueue<String> bq){
        this.bq = bq;
    }

    @Override
    public void run() {
        String[] strColl = new String[]{
                "Java",
                "Kotlin",
                "JavaScript"
        };

        for(int i = 0; i < 1000; i ++){
            try {
                System.out.println(getName() + "开始动工" + i);
                bq.put(strColl[i % 3]);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        System.out.println(getName() + "工作结束");
    }

    public static void main(String[] args){
        BlockingQueue<String> bq = new ArrayBlockingQueue<>(5);
        new BlockingQueueThread(bq).start();
    }
}

image

As you can see, when Thread-0 runs to the 6th time, it has been blocked and cannot add content to it.

6. Thread groups and unhandled exceptions

  • ThreadGroupRepresents the thread group, which can classify and manage a batch of threads
  • The child thread is in the same thread group as the parent thread that created it
  • ThreadGroupmethod
Method name effect
int activeCount Returns the number of active threads in the thread group
interrupt Interrupt the number of all active threads in this thread group
isDaemon Whether the thread group is a background thread group
setDaemon Set up background threads
setMaxPriority Set the highest priority of the thread group

7. Thread Pool

  • The thread pool creates a large number of idle threads when the system starts
  • The program passes an Runnableobject or Callableobject to the thread pool, and the thread pool will start an idle thread to execute them
  • The thread ends without death, but returns to the idle state
  • ***Java8*** added a new Executorsfactory class to produce thread pool

7.1 ThreadPool

public class ThreadPoolTest {

    public static void main(String[] args){
        ExecutorService pool = Executors.newFixedThreadPool(2);

        java.lang.Runnable target = () -> {
           for (int i = 0; i < 100 ; i ++){
               System.out.println(Thread.currentThread().getName() + "的i为" +i);
           }
        };

        pool.submit(target);
        pool.submit(target);
        pool.shutdown();
    }
}

image

7.2 ForkJoinPool

  • Split a task into multiple small tasks for parallel calculation, and then merge the results of multiple small tasks into a total calculation result
  • ForkJoinPoolYes ExecutorServiceimplementation class
public class PrintTask extends RecursiveAction {

    public static int THREADSH_HOLD = 50;

    private int start;

    private int end;

    public PrintTask(int start, int end){
        this.start = start;
        this.end = end;
    }

    @Override
    protected void compute() {
        if(end - start < THREADSH_HOLD){
            for(int i = start; i < end; i ++){
                System.out.println(Thread.currentThread().getName() + "的i为" + i);
            }
        } else {
            PrintTask left = new PrintTask(start, (start + end) / 2);
            PrintTask right = new PrintTask((start + end) / 2 , end);
            left.fork();
            right.fork();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        PrintTask printTask = new PrintTask(0 , 300);
        ForkJoinPool pool = new ForkJoinPool();
        pool.submit(printTask);
        pool.awaitTermination(2, TimeUnit.SECONDS);
        pool.shutdown();

    }
}

image

Guess you like

Origin blog.csdn.net/Java_Yhua/article/details/110145166