Java 线程池理解

目录

1. 基本介绍

(1) 概念 Java Thread pool

(2) 优势 Advantage of Java Thread Pool

(3) 例子:

2. 重要类

执行器:

工作线程   

任务

3. 执行过程

4. 补充介绍概念(这里的例子很好理解,多看):

线程池参考网页:

Java API 文档:ThreadPoolExecutor (Java Platform SE 7 )

Stackoverflow上的问题: java - How Threadpool re-use Threads and how it works - Stack Overflow

简单介绍的网址: Java Thread Pool | Thread Pooling in Java - javatpoint

1. 基本介绍

(1) 概念 Java Thread pool

 represents a group of worker threads that are waiting for the job and reuse many times.

In case of thread pool, a group of fixed size threads are created. A thread from the thread pool is pulled out and assigned a job by the service provider. After completion of the job, thread is contained in the thread pool again.

表示一组等待作业并多次重用的工作线程。

对于线程池,将创建一组固定大小的线程。从线程池中取出一个线程,并由服务提供者分配一个作业。作业完成后,线程再次包含在线程池中。

Java API 文档中的介绍:

An ExecutorService that executes each submitted task using one of possibly several pooled threads, normally configured using Executors factory methods.

一个execuorservice,它使用可能的几个池线程之一来执行每个提交的任务,通常使用executor工厂方法配置。

Thread pools address two different problems: they usually provide improved performance when executing large numbers of asynchronous tasks, due to reduced per-task invocation overhead, and they provide a means of bounding and managing the resources, including threads, consumed when executing a collection of tasks. Each ThreadPoolExecutor also maintains some basic statistics, such as the number of completed tasks.

线程池解决了两个不同的问题:它们通常在执行大量异步任务时提供更好的性能,因为减少了每个任务调用的开销;它们提供了一种方法来绑定和管理执行任务集合时消耗的资源(包括线程)。每个ThreadPoolExecutor还维护一些基本的统计信息,比如已完成任务的数量。

To be useful across a wide range of contexts, this class provides many adjustable parameters and extensibility hooks. However, programmers are urged to use the more convenient Executors factory methods Executors.newCachedThreadPool() (unbounded thread pool, with automatic thread reclamation), Executors.newFixedThreadPool(int) (fixed size thread pool) and Executors.newSingleThreadExecutor() (single background thread), that preconfigure settings for the most common usage scenarios. Otherwise, use the following guide when manually configuring and tuning this class:

为了适用于各种上下文,这个类提供了许多可调参数和可扩展钩子。但是,程序员应该使用更方便的Executors. newcachedthreadpool()(无边界线程池,具有自动线程回收),Executors. newfixedthreadpool (int)(固定大小线程池)和Executors. newsinglethreadexecutor()(单个后台线程),为最常见的使用场景预配置Settings。否则,在手动配置和调优该类时,请使用以下指南: (略)

(2) 优势 Advantage of Java Thread Pool

Better performance It saves time because there is no need to create new thread.

Java线程池的优势

更好的性能节省时间,因为不需要创建新的线程。

(3) 例子:

File: WorkerThread.java

package com.example.javatest.threadpool;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

public class WorkerThread implements Runnable {
    private String workName;

    public WorkerThread(String msg) {
        workName = msg;
    }

    @Override
    public void run() {
        System.out.println(getCurrentTime() + "******" + Thread.currentThread().getName() + " (Start) workName = " + workName);
        processmessage();//call processmessage method that sleeps the thread for 2 seconds
        System.out.println(getCurrentTime() + "******" + Thread.currentThread().getName() + " (End)");//prints thread name
    }

    private void processmessage() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public String getCurrentTime() {
        Date date = new Date();
        String strTime;

        DateFormat dateFormat = new SimpleDateFormat("MM-dd HH:mm:ss");
        strTime = dateFormat.format(date);
        //System.out.println(strTime);

        return strTime;
    }
}

File: JavaThreadPoolExample.java

package com.example.javatest.threadpool;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class JavaThreadPoolExample {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(5);//creating a pool of 5 threads
        for (int i = 0; i < 10; i++) {
            Runnable worker = new WorkerThread("" + i);
            System.out.println(getCurrentTime() + "######" + "execute worker=" + i);
            executor.execute(worker);//calling execute method of ExecutorService
        }
        executor.shutdown();
        System.out.println(getCurrentTime() + "######" + "shut donw");
        while (!executor.isTerminated()) {
        }

        System.out.println(getCurrentTime() + "######" + "Finished all threads");
    }

    public static String getCurrentTime() {
        Date date = new Date();
        String strTime;

        DateFormat dateFormat = new SimpleDateFormat("MM-dd HH:mm:ss");
        strTime = dateFormat.format(date);
        //System.out.println(strTime);

        return strTime;
    }
}

输出:

05-19 16:11:57######execute worker=0
05-19 16:11:57######execute worker=1
05-19 16:11:57######execute worker=2
05-19 16:11:57######execute worker=3
05-19 16:11:57******pool-1-thread-1 (Start) workName = 0
05-19 16:11:57######execute worker=4
05-19 16:11:57######execute worker=5
05-19 16:11:57######execute worker=6
05-19 16:11:57######execute worker=7
05-19 16:11:57######execute worker=8
05-19 16:11:57######execute worker=9
05-19 16:11:57******pool-1-thread-3 (Start) workName = 2
05-19 16:11:57######shut donw
05-19 16:11:57******pool-1-thread-2 (Start) workName = 1
05-19 16:11:57******pool-1-thread-5 (Start) workName = 4
05-19 16:11:57******pool-1-thread-4 (Start) workName = 3
05-19 16:11:59******pool-1-thread-1 (End)
05-19 16:11:59******pool-1-thread-1 (Start) workName = 5
05-19 16:11:59******pool-1-thread-3 (End)
05-19 16:11:59******pool-1-thread-3 (Start) workName = 6
05-19 16:11:59******pool-1-thread-2 (End)
05-19 16:11:59******pool-1-thread-2 (Start) workName = 7
05-19 16:11:59******pool-1-thread-5 (End)
05-19 16:11:59******pool-1-thread-4 (End)
05-19 16:11:59******pool-1-thread-4 (Start) workName = 8
05-19 16:11:59******pool-1-thread-5 (Start) workName = 9
05-19 16:12:01******pool-1-thread-1 (End)
05-19 16:12:01******pool-1-thread-4 (End)
05-19 16:12:01******pool-1-thread-5 (End)
05-19 16:12:01******pool-1-thread-2 (End)
05-19 16:12:01******pool-1-thread-3 (End)
05-19 16:12:01######Finished all threads

可以看出,当线程池只有5个线程,有10个任务需要执行时,当有空闲线程时,分配给任务执行; 当没有空闲线程时,等待有线程空闲时再执行。

2. 重要类

执行器

Executor  接口, 定义一个执行任务的方法, execute(Runnable command),  其中参数command为传入的任务  (看做参数注入,依赖倒置和合成复用原则???)

ExecutorService  继承Executor, 并拓展方法

ThreadPoolExecutor  提供一个线程池的基本实现 (父类为AbstractExecutorService)

Executors  提供工厂方法,创建具体的Executor

工作线程   

WorkerThread (, 指java 库中的,并非上面自己定义的)

任务

  Task

3. 执行过程

ThreadPoolExecutor.execute  -> addWorker (Worker为内部类, 它实现了Runnable接口,并持有最初的参数command即Runnable的子类) ,

添加成功调用 start() 启动, 则回调Worker 类的 run()方法,  再调用实际上要处理的command任务的 run()方法

addWorker(command, true/false) -> new Worker(command) .start -> Worker.run() -> command.run()

4. 补充介绍概念(这里的例子很好理解,多看):

https://www.baeldung.com/thread-pool-java-and-guava

在Java中,线程被映射到作为操作系统资源的系统级线程。如果不受控制地创建线程,可能会很快耗尽这些资源。
线程之间的上下文切换也由操作系统来完成——以便模拟并行性。一种简单的观点是——生成的线程越多,每个线程用于实际工作的时间就越少
线程池模式有助于在多线程应用程序中节省资源,并在某些预定义的限制中包含并行性

5. 中文介绍

Java并发编程:线程池的使用 - Matrix海子 - 博客园

其它使用线程池的原因

(侧面)  创建一个线程花销大: java - Why is creating a Thread said to be expensive? - Stack Overflow

  • 必须为线程堆栈分配和初始化一大块内存
  • 需要进行系统调用,以便在主机操作系统中创建/注册本机线程
  • 需要创建、初始化描述符并将其添加到jvm内部数据结构中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值