Java Concurrency 10--Use of Thread Concurrency Library



1. The concept of thread pool

  After java5, there is the function of thread pool. Before introducing thread pool, let's take a brief look at the concept of thread pool. Suppose I open a consulting company, so many people will come to ask questions every day. If I receive one by one, there must be a lot of people queuing up, so the efficiency is very poor. I want to solve this problem, and now I hire a few customer service personnel. , when there is a consultation, I will assign a customer service to receive him, and another one, I will assign another customer service to receive... If the first customer service is finished, I will let her receive the next inquirer, so that I hire These customer service can be recycled. These clients are like different threads, so the container that holds these threads is called a thread pool.

2. Use of Executors

  The Executors tool class is used to create a thread pool. This thread pool can specify the number of threads or not, or it can specify the thread pool of the timer. It has the following common methods:

method name effect
newFixedThreadPool(int nThreads) Create a fixed number of thread pools
newCachedThreadPool() Create a cached thread pool
newSingleThreadExecutor () Create a single thread
newScheduledThreadPool(int corePoolSize) Create a timer thread pool

2.1 Fixed number of thread pools

  Let's first look at the use of the Executors tool class:

public class ThreadPool {
//线程池的概念与Executors类的使用
    public static void main(String[] args) {
        //固定线程池:创建固定线程数去执行线程的任务,这里创建三个线程
        ExecutorService threadPool = Executors.newFixedThreadPool(3);

        for (int i = 1; i <= 10; i++) {//向池子里扔10个任务
            final int task = i;
            threadPool.execute(new Runnable() {//execute方法表示向池子中扔任务,任务即一个Runnable

                @Override
                public void run() {
                    for (int j = 1; j <= 5; j++) { 
                        try {
                            Thread.sleep(20);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName()
                                + " looping of " + j + " for task of " + task);
                    }
                }
            });
        }
        System.out.println("all of 10 tasks have committed!");
        threadPool.shutdown(); //执行完任务后关闭
//      threadPool.shutdownNow(); //立即关闭
    }
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

  As can be seen from the code, with the Executors tool class, it is convenient for us to create a fixed number of threads, all of which do the same task. threadPool.execute means to take a thread from the pool to execute the task. Three threads are defined above, so three tasks are taken each time to let the thread execute, and other tasks wait. After the execution is completed, three tasks are taken from the pool. Execute, after execution, take three more tasks, and one of the three threads of the last task will grab the execution. Therefore, if the number of threads is defined, the number of tasks will be executed each time, because one thread is one task, and other tasks will be executed after execution.
  Because there are a lot of execution results, I will not post the results. Anyway, three tasks are executed each time until 10 tasks are executed.

2.2 Cache thread pool

  The so-called cache thread pool means that the number of threads is not fixed. When a task comes, I open one thread to serve it, two tasks I open two, and N tasks I open N threads to serve it. If there is only one task left now, after a period of time, the redundant thread will be killed and one thread will be reserved for it. So you can rewrite the above code:

public class ThreadPool {
//线程池的概念与Executors类的使用
    public static void main(String[] args) {
        //缓存的线程池
        //自动根据任务数量来设定线程数去服务,多了就增加线程数,少了就减少线程数
        //这貌似跟一般情况相同,因为一般也是一个线程执行一个任务,但是这里的好处是:如果有个线程死了,它又会产生一个新的来执行任务
        ExecutorService threadPool = Executors.newCachedThreadPool();
        for (int i = 1; i <= 10; i++) {//扔5个任务
            final int task = i;
            threadPool.execute(new Runnable() {//向池子中扔任务,任务即一个Runnable

                @Override
                public void run() {
                    for (int j = 1; j <= 5; j++) {
                        try {
                            Thread.sleep(20);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName()
                                + " looping of " + j + " for task of " + task);
                    }
                }
            });
        }
        System.out.println("all of 10 tasks have committed!");
        threadPool.shutdown(); //执行完任务后关闭
    }
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

  When using the cache thread pool, the number of threads is automatically generated according to the number of tasks, that is, the threads follow the tasks. The running results are not posted, a little too much.
  Then create a single thread pool newSingleThreadExecutor() and write it, just change the above method, there is only one thread to execute 10 tasks, but what is the difference between this and our usual direct new thread? It also has the advantage that if the thread dies, it will automatically regenerate a new one, and our own new one will not. If the thread dies and a new one needs to be spawned, that is to say, to ensure that there is a thread executing tasks, then newSingleThreadExecutor() is a good choice.

3. Thread pool start timer

  We can use the static method newScheduledThreadPool(int corePoolSize) to define a timer thread pool, which can specify the number of threads. Then call the schedule method and pass in a Runnable and timing duration, see the code:

public class ThreadPool {

    public static void main(String[] args) {
        Executors.newScheduledThreadPool(3).schedule(new Runnable() {

            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + " bombing");
            }
        }, 2, TimeUnit.SECONDS);        
    }
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

  Three threads are defined, and one will be the first to grab the task execution and execute it after 2 seconds. This just creates a task, what if we want to use this thread pool to perform multiple tasks? Only one Runnable can be passed in the schedule, that is to say, only one task can be passed in. The solution is the same as the above programs. First get the created thread pool, and then execute the schedule multiple times in a loop, passing in a task each time. Can:

public class ThreadPool {

    public static void main(String[] args) {
        //拿到定时器线程池
        ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(3);
        for(int i = 1; i <= 5; i ++) { //执行5次任务
            threadPool.schedule(new Runnable() {

                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + " bombing");
                }
            }, 2, TimeUnit.SECONDS);
        }   
    }
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

  Because there are only 3 threads in the thread pool, but there are 5 tasks, 3 tasks will be executed first, and the remaining 2 tasks will be executed by 2 random threads. See the results:

pool-1-thread-3 bombing
pool-1-thread-2 bombing
pool-1-thread-1 bombing
pool-1-thread-2 bombing
pool-1-thread-3 bombing

  What if I want to execute a task after 5 seconds and then every 2 seconds? We can call another method scheduleAtFixedRate, which passes in a Runnable, a timing time and the time interval for each repeated execution, as follows:

public class ThreadPool {

    public static void main(String[] args) {
        Executors.newScheduledThreadPool(3).scheduleAtFixedRate(new Runnable() {

            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + " bombing");
            }
        }, 5, 2, TimeUnit.SECONDS);     
    }
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

  This will execute after 5 seconds, and every 2 seconds thereafter. There is a flaw in this method, that is, it cannot be executed at a specified time point. The solution provided by the official JDK is data.getTime()-System.currentTimeMillis()to obtain the relative time, and then put it in the second parameter of the above method.
  The use of thread concurrency library is summed up so much~

  Related reading: http://blog.csdn.net/column/details/bingfa.html




1. The concept of thread pool

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326945750&siteId=291194637