Java Concurrent Programming (02): thread core mechanism, basic concept extension

Source code: GitHub point here || GitEE point here

1, Thread basic mechanism

1. Concept description

The characteristic of concurrent programming is that it can divide the program into several separate and independent tasks, and drive these independent tasks to execute through threads, so as to improve the overall efficiency. Here is a basic demonstration.

2. Application cases

Scenario: suppose there is a container set, and each element in the container needs to be taken out for processing. In general, it's better to traverse directly. If the data is too large, you can cut the set according to the number of threads, and each thread processes a part of the data, so the processing time will be greatly reduced.

public class ExtendThread01 {
    public static void main(String[] args) {
        List<Object> dataList = new ArrayList<>() ;
        dataList.add("A");
        dataList.add("B");
        dataList.add("C");
        // Cut a large set into 2 elements of each subset
        List<List<Object>> splitList = splitList(dataList,2);
        for (List<Object> list:splitList){
            System.out.println(list);
        }
        // Multithreading
        for (List<Object> childList:splitList){
            ListTask listTask = new ListTask(childList) ;
            Thread runThread = new Thread(listTask);
            runThread.start();
        }
    }
    /**
     * List Set cut
     */
    private static List<List<Object>> splitList (List<Object> list, int childSize) {
        if (list == null || list.size() == 0 || childSize < 1) {
            return null;
        }
        List<List<Object>> result = new ArrayList<>();
        int size = list.size();
        int count = (size + childSize - 1) / childSize ;
        for (int i = 0; i < count; i++) {
            List<Object> subList = list.subList(i * childSize, ((i + 1) * childSize > size ? size : childSize * (i + 1)));
            result.add(subList);
        }
        return result;
    }
}
class ListTask implements Runnable {
    private List<Object> list ;
    public ListTask (List<Object> list){this.list=list;}
    @Override
    public void run() {
        for (Object object:list){
            System.out.println(Thread.currentThread().getName()+"=="+object);
        }
    }
}

Note: the case here is only the implementation of scenario principle. In the development, this operation is not allowed. It needs to use Thread pool for processing, which will be said later. If the collection is not well controlled, a large number of Thread threads will be created, resulting in memory overflow.

2, Thread stop start

1. Basic process

After the thread is started, it can be blocked, dormant, awakened, stopped and a series of state operations.

Thread sleep function: when a part of the tasks of a thread are executed and enter the sleep (blocking) state, the thread scheduler can switch to another thread, which is relatively fair to the execution of distributed tasks.

2. Use cases

public class ExtendThread02 {
    public static void main(String[] args) {
        StopThread stopThread = new StopThread() ;
        stopThread.start();
        // Marks the current thread stop signal, and throws an interrupt exception, but does not stop
        stopThread.interrupt();
        // Determine whether the current thread is already in termination state
        System.out.println("1=="+stopThread.isInterrupted());
        // Clear the termination signal of the current thread
        System.out.println("2=="+stopThread.interrupted());
        // Judge the current thread state again
        System.out.println("3=="+stopThread.isInterrupted());
        System.out.println("main end ...");
    }
}
class StopThread extends Thread {
    @Override
    public void run() {
        for (int i = 0 ; i < 10 ; i++){
            try {
                System.out.println(Thread.currentThread().getId()+"="+i);
                // Thread blocked for 1 second
                Thread.sleep(1000);
            } catch (InterruptedException e){
                e.printStackTrace();
            }
        }
    }
}

3. Core approach

sleep(long millis): a thread sleeps for a specified time and enters a blocking state;

interrupt(): switch the thread to the interrupt state, throw an interrupt exception, and do not stop the thread. You can monitor the thread's interrupt state and define the execution strategy.

interrupted(): clear the interrupt status of the thread calling this method, and it will not affect the execution of the thread, and return whether the thread currently executing 'stopThread.interrupted()' is interrupted, which means whether the main thread is interrupted.

isInterrupted(): determines whether the thread calling the method is already in an interrupted state.

One sentence of tool Mending: these methods of thread are extremely easy to confuse. You need to trace the breakpoint source code, enter the source code method, and call the relevant API to check the status. (attach a breakpoint diagram:)

3, Thread priority

1. Basic concepts

The order of CPU execution and processing threads is uncertain, but thread scheduler tends to execute threads with high thread priority. High thread priority indicates high probability of acquiring CPU resources, or multiple execution time segments, but it does not mean the final execution with low priority.

2. Use cases

public class ExtendThread03 {
    public static void main(String[] args) {
        Priority01 priority01 = new Priority01();
        priority01.start();
        System.out.println("priority01="+priority01.getPriority());
        Priority02 priority02 = new Priority02();
        priority02.start();
        System.out.println("priority02="+priority02.getPriority());
        priority01.setPriority(10);
        priority02.setPriority(1);
    }
}
class Priority01 extends Thread {
    @Override
    public void run() {
        for (int i = 0 ; i < 100 ; i++){
            System.out.println(Thread.currentThread().getName()+";i="+i);
        }
    }
}
class Priority02 extends Thread {
    @Override
    public void run() {
        for (int a = 0 ; a < 100 ; a++){
            System.out.println(Thread.currentThread().getName()+";a="+a);
        }
    }
}

Note: if the priority range [MAX_PRIORITY=10, MIN_PRIORITY=1] is exceeded, an IllegalArgumentException exception will be thrown.

Suggestion: in general, in actual development, it is not allowed to easily modify the parameters of thread running, which is easy to cause exceptions other than cognition.

4, Thread join

1. Basic concepts

If the join method of thread B is executed in thread A, thread A will wait for thread B to finish execution before returning to continue execution.

2. Use cases

public class ExtendThread04 {
    public static void main(String[] args) {
        JoinThreadA joinThreadA = new JoinThreadA() ;
        joinThreadA.start();
    }
}
class JoinThreadA extends Thread {
    @Override
    public void run() {
        System.out.println("In water shortage...");
        JoinThreadB joinThreadB = new JoinThreadB() ;
        joinThreadB.start();
        try{
            joinThreadB.join();
        } catch (Exception e){
            e.printStackTrace();
        }
        System.out.println("Drinking water...");
    }
}
class JoinThreadB extends Thread {
    @Override
    public void run() {
        System.out.println("Buy water...");
        try{
            TimeUnit.SECONDS.sleep(2);
        } catch (Exception e){
            e.printStackTrace();
        }
        System.out.println("Buy water...");
    }
}

Note: you can set the join time (long) of threads. After all, you can't wait for the snow and the moon to bloom. You have time difference in your life, so you can only meet later.

5, Local thread

1. Basic concepts

Local thread variable, the underlying maintenance ThreadLocalMap storage value:

static class Entry extends WeakReference<ThreadLocal<?>> {
    Object value;
    Entry(ThreadLocal<?> k, Object v) {
        super(k);
        value = v;
    }
}

That is, data is stored in the way of key value pairs. If you are familiar with the source code of the collection container, this Entry is a sense of deja vu.

2. Use cases

public class ExtendThread05 {
    private static final ThreadLocal<Long> threadLocal = new ThreadLocal<>() ;
    private static void initBegin (){
        threadLocal.set(System.currentTimeMillis());
    }
    private static Long overTime (){
        return System.currentTimeMillis()-threadLocal.get();
    }
    public static void main(String[] args) throws Exception {
        ExtendThread05.initBegin();
        TimeUnit.SECONDS.sleep(3);
        System.out.println(ExtendThread05.overTime());
    }
}

ThreadLocal provides the ability of thread memory to store variables, and is bound to the current thread. Through get and set methods, you can get the value corresponding to the current thread. This is a common application in web development.

6, Daemons

1. Basic concepts

Daemons are auxiliary threads, which play a scheduling and supporting role in the program. When all non daemons in the Jvm end, the daemons will also end.

2. Use cases

public class ExtendThread06 {
    public static void main(String[] args) throws Exception {
        InputStreamReader is = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(is);
        String value = br.readLine();
        CheckThread checkThread = new CheckThread(value) ;
        checkThread.setDaemon(true);
        checkThread.start();
        System.out.println("Main End ...");
    }
}
class CheckThread extends Thread {
    private String spell ;
    public CheckThread (String spell){
        this.spell = spell ;
    }
    @Override
    public void run() {
        if (spell.startsWith("cs")){
            System.out.println(spell+": Input correct");
        } else {
            System.out.println(spell+": Input error");
        }
        try {
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}

Note: the daemons need to explicitly call setDaemon(true); method, here you can see that the main thread is over, and the integrator is over, regardless of the daemons in sleep. If you interrupt the sleep of non Guardian threads, will you face an exception?

7, Thread exception handling

1. Mechanism description

According to the exception handling mechanism in Java, throwing exceptions is reduced step by step. If the task method run of a thread does not throw exceptions, the rewritten or implemented method cannot throw exceptions directly. It is recommended to catch exceptions in multithreading, which can be handled specifically.

2. Use cases

public class ExtendThread07 {
    public static void main(String[] args) {
        TryThread tryThread = new TryThread();
        tryThread.setName("try-name");
        // Define exception handling strategy in operation
        MyExe myExe = new MyExe() ;
        tryThread.setUncaughtExceptionHandler(myExe);
        tryThread.start();
    }
}
class TryThread extends Thread {
    @Override
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e){
            e.printStackTrace();
        }
        // How to deal with the exception here?
        Integer.parseInt("cicada") ;
    }
}
class MyExe implements Thread.UncaughtExceptionHandler {
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        System.out.println(t.getName()+";Exception:"+e.getMessage());
    }
}

By implementing the UncaughtExceptionHandler interface, and the thread needs to specify a custom exception handling object, it can also handle unchecked exceptions.

8, Source code address

GitHub·address
https://github.com/cicadasmile/java-base-parent
GitEE·address
https://gitee.com/cicadasmile/java-base-parent

Tags: Programming github Java Web Development

Posted on Sun, 15 Mar 2020 06:27:14 -0400 by talper