一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

Java线程池的实现示例

时间:2016-08-11 编辑:简简单单 来源:一聚教程网

最近在写Java程序的时候,接触到一些多线程方面的东西,用到了Java中的线程池。JDK中对线程池的支持比较完善,在java.util.concurrent包中,用ThreadPoolExecuter类表示一个线程池,同时还有一个Executor类扮演着线程池工厂的角色。例如:

 

 代码如下 复制代码
public static ExecutorService newFixedThreadPool(int nThreads)
public static ExecutorService newSingleThreadExecutor()
public static ExecutorService newCachedThreadPool()
...

这些工厂方法,从本质上,都是调用了ThreadPoolExecutor类的构造函数:

 

 代码如下 复制代码
public ThreadPoolExecutor(int corePoolSize,
                    int maximumPoolSize,
                    long keepAliveTime,
                    TimeUnit unit,
                    BlockingQueue workQueue,
                    ThreadFactory threadFactory,
                    RejectedExecutionHandler handler)

参数含义如下:

corePoolSize:线程池中应该保持的线程数量,即使线程空闲
maximumPoolSize:线程池中最大线程的数量
keepAliveTime:当线程数量大于corePoolSize时,指定空闲线程存在多久会被销毁
unit:keepAliveTime的单位
workQueue:任务队列,被提交但还没有执行
threadFactory:线程工厂
handler:拒绝策略

实现思路

从ThreadPoolExecutor的构造函数中,我们大概知道实现一个线程池需要哪些东西,如果完全按照构造函数中的参数来的话,太麻烦,有太多地方需要考虑,因此实现一个简单版的。

首先需要考虑线程池中存放多少线程。可以简单用一个变量来指定,并且这些线程要放在一个容器里,便于销毁,也便于知道他们的状态。
然后我们要考虑一个作为任务队列的容器。假如线程池中有5个线程,如果5个线程都处于工作状态的话,这时候送来的任务就需要放在任务队列中等待。
最后是线程池中工作线程的形式。工作线程在创建时开始就应该启动,其所做的工作主要是:从任务队列中取出任务-执行任务这样的无限循环。
工作线程的一种实现方式:

 

 代码如下 复制代码

class WorkerThread extends Thread {
    private Boolean isRunning = true;
   
    public void close() {
        isRunning = false;
    }

    public void run() {
        while (isRunning) {
            Runnable task = null;
            try {
                task = taskQueue.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            task.run();
        }
    }
}

WorkerThread是线程池的内部类,其中,taskQueue是任务队列,这里采用了BlockingQueue接口的一种实现,其put和take方法都是阻塞的。提交任务和销毁线程池如下:

 

 代码如下 复制代码

public void submit(Runnable task) {
    if (currentWorking() < limits) {
        WorkerThread worker = new WorkerThread();
        worker.start();
        workers.add(worker);
    }
    try {
        taskQueue.put(task);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

public void destroy() {
    while (!taskQueue.isEmpty());
    for (WorkerThread worker : workers) {
        worker.close();
    }
}

完整代码在这里。

 代码如下 复制代码

import java.util.ArrayList;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * Created by rahul on 7/20/16.
 */
public class SimpleThreadPool {
    public static BlockingQueue testQueue = new LinkedBlockingQueue<>();

    private int limits;
    private ArrayList workers;
    private BlockingQueue taskQueue;

    SimpleThreadPool(int nums) {
        limits = nums;
        workers = new ArrayList<>();
        taskQueue = new LinkedBlockingQueue<>();
    }

    private int currentWorking() {
        return workers.size();
    }

    public void submit(Runnable task) {
        if (currentWorking() < limits) {
            WorkerThread worker = new WorkerThread();
            worker.start();
            workers.add(worker);
        }
        try {
            taskQueue.put(task);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void destroy() {
        while (!taskQueue.isEmpty());
        for (WorkerThread worker : workers) {
            worker.close();
        }
    }

    class WorkerThread extends Thread {
        private Boolean isRunning = true;

        public void close() {
            isRunning = false;
        }

        public void run() {
            while (isRunning) {
                Runnable task = null;
                try {
                    task = taskQueue.take();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                task.run();
            }
        }
    }

    public static void main(String[] args) {
        SimpleThreadPool pool = new SimpleThreadPool(10);
        for (int i = 0; i < 100; ++i) {
            pool.submit(new test("Task " + i));
        }
        pool.destroy();
    }
}

class test implements Runnable {
    private String id;

    public test(String str) { id = str; }

    public void run() {
        try {
            System.out.println("Start process " + id);
            Thread.sleep(1000);
            System.out.println(id + " Completed!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

线程池看似简单,其实很复杂,因为如果真要到一个应用级别的话,要考虑的东西还有很多,例如何时该启动一个线程,何时线程应该中止与挂起,任务队列的阻塞与超时,任务拒绝策略,线程生命周期等。至于本文实现的线程池

热门栏目