使用Lock(ReentrantLock)结合Condition实现自定义线程池

声明:

  1、该篇只是提供一种自定义线程池的实现方式,可能性能、安全等方面需要优化;

  2、该篇自定义线程池使用Lock(可重入锁ReentrantLock)结合Condition来实现;

  3、该篇力求使用简单的方式呈现,如有错误之处,欢迎指正,在此表示感谢。

概述

  自定义线程池三要素包括:

  1、存储线程的容器(或叫线程池)。该容器可使用数组或链表,容器中存放执行线程,本篇使用链表实现。

  2、执行线程(或叫执行器)。具体执行的线程。

  3、执行任务。执行线程需要执行的具体任务。

代码

/**
 * 任务接口
 *
 */
public interface Task {

    /**
     * 执行任务
     */
    void executeTask();

}
/**
 * 执行接口
 *
 */
public interface Executor {

    /**
     * 设置任务
     *
     * @param task 任务
     */
    void setTask(Task task);

    /**
     * 获取任务
     *
     * @returnTask
     */
    Task getTask();

    /**
     * 启动任务
     */
    void startTask();

}
/**
 * 线程池接口
 *
 */
public interface Pool {

    /**
     * 获取执行线程
     *
     * @return Executor
     */
    Executor getExecutor();

    /**
     * 销毁线程池
     */
    void destory();

}
/**
 * 线程池实现类
 *
 */
public class ThreadPool implements Pool {

    //是否开启线程池,true-开启,false-关闭
    private boolean isOpen = true;

    //默认执行线程数量
    private final static int DEFAULT_THREAD_NUM = 6;

    //执行线程数量,默认为DEFAULT_THREAD_NUM
    private static int THREAD_NUM = DEFAULT_THREAD_NUM;

    //存放执行线程的容器
    private LinkedList<Executor> container = new LinkedList<Executor>();

    //可重入锁
    private Lock lock = new ReentrantLock();

    //condition
    private Condition condition = lock.newCondition();

    public ThreadPool(int threadNum){
        isOpen = true;
        THREAD_NUM = threadNum > 0 ? threadNum : THREAD_NUM;
        for(int i = 0;i < THREAD_NUM;i++){
            Executor executor = new ExecutorImpl();
            ((ExecutorImpl)executor).setName("执行线程" + i);
            container.add(executor);//将执行线程加入容器中
            ((ExecutorImpl)executor).start();//启动执行线程
        }
    }

    public ThreadPool(){
        this(DEFAULT_THREAD_NUM);
    }

    @Override
    public Executor getExecutor() {
        Executor executor = null;
        try{
            lock.lock();//加锁
            if(container.size() > 0){
                executor = container.removeFirst();
            }else{
                condition.await();//等待,释放锁
                executor = container.removeFirst();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally{
            lock.unlock();//释放锁
        }
        return executor;
    }

    @Override
    public void destory() {
        try{
            lock.lock();//加锁
            isOpen = false;
            condition.signalAll();//通知
            container.clear();
        }finally{
            lock.unlock();//释放锁
        }

    }

    private class ExecutorImpl extends Thread implements Executor{

        //执行任务
        private Task task;

        //可重入锁
        private Lock innerLock = new ReentrantLock();

        //condition
        private Condition innerCondition = innerLock.newCondition();

        public void run(){
            while(isOpen){
                try{
                    System.out.println(Thread.currentThread().getName() + " 启动   <<<<<<<<");
                    innerLock.lock();;//加锁
                    System.out.println(Thread.currentThread().getName() + " 等待   >>>>>>>>");
                    innerCondition.await();//等待
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally{
                    innerLock.unlock();//释放锁
                }
                System.out.println(Thread.currentThread().getName() + " 执行任务  ........");
                getTask().executeTask();//执行任务
                //任务执行完,放回容器中
                try{
                    lock.lock();//加锁
                    //将该执行线程放回容器中
                    System.out.println(Thread.currentThread().getName() + " 返回容器  。。。。。。。。");
                    container.add(ExecutorImpl.this);
                    System.out.println(container);
                    condition.signalAll();//通知
                }finally{
                    lock.unlock();//释放锁
                }
            }
        }

        @Override
        public void setTask(Task task) {
            this.task = task;
        }

        @Override
        public Task getTask() {
            return this.task;
        }

        @Override
        public void startTask() {
            try{
                innerLock.lock();//加锁
                innerCondition.signal();//通知
            }finally{
                innerLock.unlock();//释放锁
            }
        }

    }

}
public class Test {

    public static void main(String[] args) throws InterruptedException {

        Pool pool = new ThreadPool(2);

        for(int i = 0;i < 2;i++){
            Executor executor = pool.getExecutor();
            Task task = new PrintTask();
            executor.setTask(task);
            executor.startTask();
        }

        pool.destory();

    }

}
执行线程0 启动   <<<<<<<<
执行线程1 启动   <<<<<<<<
执行线程1 等待   >>>>>>>>
执行线程0 等待   >>>>>>>>
执行线程0 执行任务  ........
执行线程0执行了打印任务
执行线程0 返回容器  。。。。。。。。
执行线程1 执行任务  ........
执行线程1执行了打印任务
[Thread[执行线程0,5,main]]
执行线程1 返回容器  。。。。。。。。
[Thread[执行线程0,5,], Thread[执行线程1,5,main]]

  

时间: 2024-10-12 23:28:47

使用Lock(ReentrantLock)结合Condition实现自定义线程池的相关文章

使用wait()和notifyAll()方法自定义线程池

声明: 1.该篇只是提供一种自定义线程池的实现方式,可能性能.安全等方面需要优化: 2.该篇自定义线程池使用的是wait()和notifyAll()方法,也可以使用Lock结合Condition来实现: 3.该篇力求使用简单的方式呈现,如有错误之处,欢迎指正,在此表示感谢. 概述 自定义线程池三要素包括: 1.存储线程的容器(或叫线程池).该容器可使用数组或链表,容器中存放执行线程,本篇使用链表实现. 2.执行线程(或叫执行器).具体执行的线程. 3.执行任务.执行线程需要执行的具体任务. 代码

c#网络通信框架networkcomms内核解析之十 支持优先级的自定义线程池

本例基于networkcomms2.3.1开源版本  gplv3协议 如果networkcomms是一顶皇冠,那么CommsThreadPool(自定义线程池)就是皇冠上的明珠了,这样说应该不夸张的,她那么优美,简洁,高效. 在 <c#网络通信框架networkcomms内核解析之六 处理接收到的二进制数据>中我们曾经提到,服务器收到数据后,如果是系统内部保留类型数据或者是最高优先级数据,系统会在主线程中处理,其他的会交给自定义线程池进行处理. 作为服务器,处理成千上万的连接及数据,单线程性能

java多线程(四)-自定义线程池

当我们使用 线程池的时候,可以使用 newCachedThreadPool()或者 newFixedThreadPool(int)等方法,其实我们深入到这些方法里面,就可以看到它们的是实现方式是这样的. 1 public static ExecutorService newCachedThreadPool() { 2 return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 3 60L, TimeUnit.SECONDS, 4 new Synchro

Java自定义线程池详解

自定义线程池的核心:ThreadPoolExecutor 为了更好的控制多线程,JDK提供了一套线程框架Executor,帮助开发人员有效的进行线程控制,其中在java.util.concurrent包下,是JDK并发包的核心,比如我们熟知的Executors.Executors扮演着线程工厂的角色,我们通过它可以创建特定功能的线程池,而这些线程池背后的就是:ThreadPoolExecutor.那么下面我们来具体分析下它. 构造ThreadPoolExecutor public ThreadP

自定义线程池

线程池: 自定义线程池一: #!/usr/bin/env python # -*- coding:utf-8 -*- import Queue import threading class ThreadPool(object): def __init__(self, max_num=20): self.queue = Queue.Queue(max_num) for i in xrange(max_num): self.queue.put(threading.Thread) def get_th

JAVA并发,线程工厂及自定义线程池

1 package com.xt.thinks21_2; 2 3 import java.util.concurrent.ExecutorService; 4 import java.util.concurrent.Executors; 5 import java.util.concurrent.SynchronousQueue; 6 import java.util.concurrent.ThreadFactory; 7 import java.util.concurrent.ThreadPo

Android 自定义线程池的实战

前言:在上一篇文章中我们讲到了AsyncTask的基本使用.AsyncTask的封装.AsyncTask 的串行/并行线程队列.自定义线程池.线程池的快速创建方式. 对线程池不了解的同学可以先看 Android AsyncTask 深度理解.简单封装.任务队列分析.自定义线程池 ------------------------------------------------------------------------------------------------------- 1.Exec

基于ThreadPoolExecutor,自定义线程池简单实现

一.线程池作用 在上一篇随笔中有提到多线程具有同一时刻处理多个任务的特点,即并行工作,因此多线程的用途非常广泛,特别在性能优化上显得尤为重要.然而,多线程处理消耗的时间包括创建线程时间T1.工作时间T2.销毁线程时间T3,创建和销毁线程需要消耗一定的时间和资源,如果能够减少这部分的时间消耗,性能将会进一步提高,线程池就能够很好解决问题.线程池在初始化时会创建一定数量的线程,当需要线程执行任务时,从线程池取出线程,当任务执行完成后,线程置回线程池成为空闲线程,等待下一次任务.JDK1.5提供了一个

使用自定义线程池优化EchoServer

在上一篇文章中http://www.cnblogs.com/gosaint/p/8494423.html 我自定义了线程池ThreadPool.现在在我的EchoServer中使用自定义线程池去负责和客户端的通讯,代码如下所示: package com.asiaInfo.caozg.ch_03.threadPool; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; imp