Java geek

Related reading:

Java Concurrent programming (1) Knowledge map Java concurrent programming (2) Atomic Java concurrent programming (3) Visibility Java concurrent programming (4) Sequential Java concurrent programming (5) Introduction to Creating threads Java concurrent programming (6) Synchronized usage Java Concurrency programming Introduction (7) Easy to understand wait and Notify and use scenarios Java concurrency programming Introduction (8) Thread lifecycle Java concurrency programming Introduction (9) Deadlock and deadlock bit Java concurrency programming Introduction (10) lock optimization Introduction to Concurrent Programming in Java (11) Flow limiting scenarios and Spring Flow Limiting scenarios Introduction to Concurrent programming in Java (12) Producer and Consumer Patterns – Introduction to Concurrent programming in Java with code templates (13) Read/write lock and cache templates (14) CountDownLatch application scenarios Introduction to Concurrent Programming in Java (15) CyclicBarrier Application Cases Introduction to Concurrent programming in Java (16) Understanding the difference between thread pools in seconds introduction to Concurrent programming in Java (18) Discussing thread safety Introduction to Concurrent programming in Java (19) Asynchronous task scheduling tool CompleteFeature Java Concurrent programming introduction (20) Common locking scenarios and locking tools


Common classes and interfaces for threads

Common classes and interfaces for threads are as follows:

1.Thread and Runnable are commonly used. The difference is that one is a class and the other is an interface. The disadvantage of classes is that they can only be inherited singly, whereas interfaces do not have this limitation.

Thread and Runnable do not return values. The result of a Thread’s execution can be obtained either through the constructor’s prior injection of an object that stores the result of the execution, or through producer-consumer mode. In order to directly obtain Thread execution results, Java packages add Callable, which can be committed through the ExecutorService rather than simply executed after Thread injection.

3.Future is the return result of thread execution in the thread pool. In addition, it can terminate the thread execution, determine the thread completion status and so on.

4. In general, the above interfaces and classes are sufficient. FutureTask provides a lightweight way to execute a thread and get the result of the thread execution without going to the left thread pool line.

FetureTask task = new FutureTask(new Callable());  // The Callable here needs to be self-implemented
Thread thread = new Thread(task); // Here you can see why FetureTask implements the Runnable interface: it can be executed as a threaded task.
V v = task.get();   // We can see that FetureTask implements the Future interface for the purpose of getting thread task execution results.
Copy the code

5.Executors is a thread pool factory that generates different types of thread pools. If Executors cause memory overflows, manually create a thread pool by using ThreadPoolExecutor.

ExecutorService is a thread-execution service that executes/commits threading tasks.

7.ThreadPoolExecutor is used to manually create thread pools and can also execute/submit thread tasks.

The above is common thread classes and interfaces, each to write a demo exercise, will soon be able to master, use can also know the chest.

Executors Create a thread pool

Although Executors are not recommended by some large factories or even provided as a code check rule, they can be used according to actual service scenarios if memory overflow does not occur.

I. Create a fixed thread pool

By Executors. NewFixedThreadPool (nThreads: int) method to create fixed-size pool, and then the ExecutorService to submit threads to execute tasks, here because there is no limit to the ExecutorService could submit how many tasks, As a result, there may be too many committed tasks that cause memory overflow. Code examples:

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

        executorService.execute(new Runnable() {
            public void run(a) {
                System.out.println(Thread.currentThread().getName() + " made rice."); }}); executorService.execute(new Runnable() {
            public void run(a) {
                System.out.println(Thread.currentThread().getName() + " made dish."); }}); executorService.execute(new Runnable() {
            public void run(a) {
                System.out.println(Thread.currentThread().getName() + " clean up table."); }}); executorService.shutdown(); }}Copy the code

Enter log:

pool-1-thread-1 made rice.
pool-1-thread-2 made dish.
pool-1-thread-2 clean up table.

Process finished with exit code 0
Copy the code

The log shows that there are two threads in the thread pool and a total of three tasks are being executed.

Create a single thread pool

By Executors. NewSingleThreadExecutor () to quickly create only one thread thread pool, submitted to multiple tasks in the thread pool can only be implemented according to the order one by one. Code examples:

public class SingleThreadDemo {

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();

        executorService.execute(new Runnable() {
            public void run(a) {
                System.out.println(Thread.currentThread().getName() + " made rice."); }}); executorService.execute(new Runnable() {
            public void run(a) {
                System.out.println(Thread.currentThread().getName() + " made dish."); }}); executorService.execute(new Runnable() {
            public void run(a) {
                System.out.println(Thread.currentThread().getName() + " clean up table."); }}); executorService.shutdown(); }}Copy the code

Output log:

pool-1-thread-1 made rice.
pool-1-thread-1 made dish.
pool-1-thread-1 clean up table.

Process finished with exit code 0
Copy the code

A single thread can perform multiple tasks.

III. Execute thread pool as planned

Tasks in the thread pool can execute as planned as shown in the following code example:

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/ * * *@ClassName ScheduledThreadPoolDemo
 * @DescriptionExecute task thread pool Demo * as scheduled@AuthorSonorous leaf *@Date2019/10/11 not *@Version1.0 * * * / javashizhan.com
public class ScheduledThreadPoolDemo {

    public static long fixedRateInterval = 0;
    public static long lastFixedRateRunTime = System.nanoTime();

    public static long withFixedInterval = 0;
    public static long lastWithFixedRunTime = System.nanoTime();

    public static void main(String[] args) {
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(3);

        // The command is executed after 1 second
        executorService.schedule(new Runnable() {
            public void run(a) {
                System.out.println(Thread.currentThread().getName() + " made rice."); }},1, TimeUnit.SECONDS);

        // The execution will start after 1 second, every 3 seconds, which is calculated from the previous task [execution start time]
        lastFixedRateRunTime = System.nanoTime();
        executorService.scheduleAtFixedRate(new Runnable() {
            public void run(a) {
                long runTime = System.nanoTime();
                fixedRateInterval = runTime - lastFixedRateRunTime;
                lastFixedRateRunTime = runTime;

                // Simulate task execution
                sleep(2);  // This hibernation time does not affect the calculation of the next execution interval, which is 3 seconds (if the task execution time is less than 3 seconds, if the task execution time is more than 3 seconds, the interval is the task execution time)
                System.out.println(Thread.currentThread().getName() + "Made dish. Interval:"+ fixedRateInterval); }},1.3,TimeUnit.SECONDS);

        // The task will be executed after 2 seconds, with an interval of 3 seconds between each task. This interval is calculated from the previous task [execution end time]
        lastWithFixedRunTime = System.nanoTime();
        executorService.scheduleWithFixedDelay(new Runnable() {
            public void run(a) {
                long runTime = System.nanoTime();
                withFixedInterval = runTime - lastWithFixedRunTime;
                lastWithFixedRunTime = runTime;

                // Simulate task execution
                sleep(2); // This sleep time will affect the calculation of the next execution interval, which is 2 seconds plus the current run time
                System.out.println(Thread.currentThread().getName() + "Clean up table. Interval:"+ withFixedInterval); }},2.3, TimeUnit.SECONDS);


    }

    public static void sleep(long millis) {
        try {
            TimeUnit.SECONDS.sleep(millis);
        } catch(InterruptedException e) { e.printStackTrace(); }}}Copy the code

Output log:

Pool-1-thread-1 made rice. Pool-1-thread-2 made dish. Interval: 1000771200 Pool-1-thread-3 clean up table. 2002448300 Pool-1-thread-2 made dish. Interval: 3000158800 Pool-1-thread-2 made dish. Interval: 3000158800 Pool-1-thread-2 made dish. Interval: 2999740199 Pool-1-thread-1 clean up table. Interval: 5001442200 Pool-1-thread-2 made dish. Interval: 3000925301 Pool-1-thread-3 clean up table. Interval: 5000781199 Pool-1-thread-1 made dish. Interval: 2999058400 Pool-1-thread-1 made dish. Interval: 3000752800 Pool-1-thread-2 Clean up table. Interval: 5001498901 Pool-1-thread-1 made dishes. Interval: 2999442900 Pool-1-thread-1 made dishes. Interval: 3001681600 Pool-1-thread-3 Clean up table. Interval: 5001714800Copy the code

You can see:

1. Made Rice executed once

2. Clean up the table 2 seconds later for the first time and 5 seconds later (task interval + Task execution time)

3. The first time is executed after 1 second, and the subsequent interval is 3 seconds (task interval time is not added, and the task execution time is less than the interval time, so the interval time is executed)

IV. Create cacheable thread pools

By Executors. NewCachedThreadPool () method can create a cache of thread pool, the default pool sizes is 0, the maximum Integer. MAX_VALUE, if there is a thread more than 60 seconds are not used will be released automatically.

Executors of each create a thread pool method is to construct by ThreadPoolExecutor, create cached thread pool to invoke a constructor is as follows:

    public static ExecutorService newCachedThreadPool(a) {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
Copy the code

The next section introduces ThreadPoolExecutor, which I won’t repeat here.

ThreadPoolExecutor creates a thread pool manually

The benefits of manually creating a thread pool from ThreadPoolExecutor include:

1. You can set the maximum thread pool size to support thread pool scaling.

2. You can use a bounded queue to store tasks to be executed to avoid memory overflow caused by too many tasks.

3. You can set the task rejection policy to be used when the task cache queue of the thread pool is full and the number of threads in the thread pool reaches maximumPoolSize.

The following is the constructor parameter definition for ThreadPoolExecutor:

The serial number The name of the type meaning
1 corePoolSize int Core thread pool size
2 maximumPoolSize int Maximum thread pool size
3 keepAliveTime long Maximum idle time for a thread, defined in the next parameter
4 unit TimeUnit Unit of time
5 workQueue BlockingQueue Thread wait queue
6 threadFactory ThreadFactory Thread creation factory
7 handler RejectedExecutionHandler Rejection policies

I. Code examples

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/ * * *@ClassName ThreadPoolExecutorDemo
 * @Description
 * @AuthorSonorous leaf *@Date 2019/10/11 16:54
 * @Version1.0 * * * / javashizhan.com
public class ThreadPoolExecutorDemo {

    public static void main(String[] args) {

        // Task queue capacity
        final int QUEUE_CAPACITY = 20;
        BlockingQueue<Runnable> runnableBlockedQueue = new LinkedBlockingDeque<Runnable>(QUEUE_CAPACITY);

        // Create a thread pool
        ThreadPoolExecutor executor = new ThreadPoolExecutor(4.10.60, TimeUnit.SECONDS, (BlockingQueue<Runnable>) runnableBlockedQueue);

        int taskNo = 0;
        int queueSize = 0;

        while (true) {
            // Randomly generate the number of tasks
            int taskNum = getTaskNum();

            for (int i = 0; i < taskNum; i++) {
                taskNo++;

                // If the queue is full, submit a new task
                if (queueSize < QUEUE_CAPACITY) {
                    executor.execute(new Worker("Task" + taskNo));
                } else {
                    If the queue is full, wait for a while and try again. Note: If the queue is full, an error will be reported because the queue capacity is exceeded.
                    while(true) {
                        sleep(200);
                        queueSize = executor.getQueue().size();
                        if (queueSize < QUEUE_CAPACITY) {
                            executor.execute(new Worker("Task" + taskNo));
                            break; } } } queueSize = executor.getQueue().size(); }}}// Randomly generate the number of tasks to execute at a time
    private static int getTaskNum(a) {
        return ((int) (1+Math.random()*(8-1+1)));
    }

    private static void sleep(long millis) {
        try {
            TimeUnit.MILLISECONDS.sleep(millis);
        } catch(InterruptedException e) { e.printStackTrace(); }}}class Worker implements Runnable {

    private String name;

    public Worker(String name) {
        this.name = name;
    }

    public void run(a) {
        exec();
    }

    // Simulate task execution
    private void exec(a) {
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(name + " be called."); }}Copy the code

Output log:

Task3 be called.
Task4 be called.
Task2 be called.
Task1 be called.
Task6 be called.
Task5 be called.
Task7 be called.
Task8 be called.
Task9 be called.
Task10 be called.
Task12 be called.
Task11 be called.
Task13 be called.
Task14 be called.
Task15 be called.
Task16 be called.
Task17 be called.
Task18 be called.
Task19 be called.
Task20 be called.
Task21 be called.
Copy the code

These are the common classes and interfaces used by threads.

end.


<– Read the mark, left like!