java线程池的实现原理

什么是线程池,换一句通俗的话来讲,就是创建若干个worker线程,在线程中执行死循环来获取任务并执行,这个死循环可以通过isinterrupt()来作为是否退出的标志

在死循环中,如果获取到任务就执行,没有任务就阻塞(wait),不能使sleep,想想sleep和wait的区别就知道:

三,实现


  1)线程池管理类
  
package poolmanager;

 /**
 * ThreadPoolManager 线程池管理类
 * @version 1.0.0
 * @see 线程池定义式样书
 * @date    2011/09/30 IterZebra
 */
//import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import systemconfig.SystemConfig;

public class ThreadPoolManager extends ThreadGroup {

    /**线程池是否开启标识*/
    int flagThreadPoolValid = 0;

    /**线程池中线程的数量,从系统配置类中获取*/
    int threadSize = SystemConfig.getThreadDefaultCount();

    /**任务队列*/
     /**
     Java 2 SE Documentation.
     Returns a synchronized (thread-safe) list backed by the specified list.
     In order to guarantee serial access, it is critical that all access to
     the backing list is accomplished through the returned list.
     根据指定的参数list,返回一个线程安全的同步的list。
     为了保证有序访问,所有的对于参数list的访问都应该通过返回的这个list去进行。
     It is imperative that the user manually synchronize
     on the returned list when iterating over it.
     如果进行迭代访问的时候,对于返回的队列应用程序本身进行同步处理是必要的。
     注:即使用迭代器访问应该使用synchronized(){}修饰代码块,使得其对list的访问进行同步;
     而如果是采用返回的list的add等方法,则应用程序本身不需要进行同步处理。

     另外由于本类中对ThreadPoolManager的访问方法都进行了同步操作,
     因此对本List的同步不是必要的。
     当然,由于加锁顺序一致性,使用对List的同步,也不会导致线程死锁。
    List<Task> TaskList= Collections.synchronizedList(new LinkedList<Task>());

    */
    List<Task> TaskList= new LinkedList<Task>();

    /**线程池管理类构造方法*/
    public ThreadPoolManager(String threadpoolname) {

         //ThreadGroup的名称
        super(threadpoolname);

        //继承自父类的方法,设置是否是守护线程
        setDaemon(true);

    }

    /**
     * @brief 开启线程池
     * @param null
     * @return void
     */
    public synchronized void threadPoolStart(){

        if(threadSize ==0 || flagThreadPoolValid !=0){

            try {
                throw new Exception();
            } catch (Exception e) {
                e.printStackTrace();
            }

            return ;
        }

        if( TaskList ==null ){

            try {
                throw new Exception();
            } catch (Exception e) {
                e.printStackTrace();
            }

            return;
        }

        // 创建并开启线程例程
        for (int i = 0;i<threadSize;i++){

             new WorkThread(i).start();

        }

        flagThreadPoolValid = 1;

    }

    /**
     * @brief 关闭线程池
     * @param null
     * @return void
     */
    public synchronized void threadPoolEnd(){

        if(threadSize ==0 || flagThreadPoolValid !=1){

            try {
                throw new Exception();
            } catch (Exception e) {
                e.printStackTrace();
            }

            return;

        }
        if(TaskList ==null ){

            try {
                throw new Exception();
            } catch (Exception e) {
                e.printStackTrace();
            }

            return;
        }

        TaskList.clear();
        threadSize = 0;
        flagThreadPoolValid = 0;

        // 继承自父类,中断ThreadGroup中添加的所有线程
        interrupt();

    }

    /**
     * @brief 向线程池管理类的任务队列中添加任务
     * @param newTask Task任务类
     * @return void
     */
    public synchronized void addTask(Task newTask){

        if(TaskList == null ){

            try {
                throw new Exception();
            } catch (Exception e) {
                e.printStackTrace();
            }

            return;
        }

        TaskList.add(newTask);

        //唤醒一个正在getTask()方法中等待任务的工作线程
        notify();

    }

    /**
     * @brief 获取线程池中任务队列中的任务
     * @param null
     * @return Task类
     */
    public synchronized Task getTask(){

        if(TaskList ==null ){

            try {
                throw new Exception();
            } catch (Exception e) {
                e.printStackTrace();
            }

            return null;
        }
        /**
         Java 2 SE Documentation.
          As in the one argument version,
          interrupts and spurious wakeups are possible,
          and this method should always be used in a loop.
          正如具有一个参数的函数版本,
          由于wait()函数调用过程中可能发生中断、虚假唤醒,
          因此这个方法必须在检测循环中使用。
          另外,在这里,如果不使用while循环,存在如下一种问题:
          抛出地址越界异常。
          例如:
          主线程添加了一个任务,这样会唤醒一个线程。在这个线程被唤醒执行。
          此时主线程添加另外一个任务,又唤醒一个线程。
          第一个线程其抓取任务后,继续抓取下一个任务执行,也就是抓取添加的第二个任务。
          这样队列中已经不存在任务。第二个被唤醒的线程必然在执行remove(0)的时候抛出上述异常。

          而且也不能仅仅是if判断,因为唤醒获取锁后,
          会直接执行wait()后的代码,只有while可以达到进行判断的目的。
        */
        while(TaskList.size() == 0 ){

            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }

        return  TaskList.remove(0);

    }

    /**
     * @brief 内部类,工作线程类
     */
    private class WorkThread extends Thread{

        public WorkThread(int threadID) {

            //父类构造方法,将线程加入到ThreadGroup中
            super(ThreadPoolManager.this,""+threadID);
        }

        /**
          * @brief 重写父类Thread的run方法
          * @param null
          * @return void
          */
        public void run(){

            //isInterrupted()方法继承自Thread类,判断线程是否被中断
            while(! isInterrupted()){

                Task runTask = getTask();

                //getTask()返回null或者线程执行getTask()时被中断
                if(runTask == null)    break ;

                runTask.run();

            }

        }

    }
}


  2)任务类


package poolmanager;

public abstract class Task implements Runnable {

    public void run() {
    }

}

//系统配置类


package systemconfig;

public class SystemConfig {
    
    static final int THREAD_DEFAULT_COUNT = 10;
    
    public static int getThreadDefaultCount() {
        return THREAD_DEFAULT_COUNT;
    }
    

}
  3)测试  
package poolmanager.test;

import poolmanager.Task;

public class TestTask extends Task {

    private   int i ;

    public TestTask(int i) {
        this.i = i;

    }

    public void run() {
        System.out.println("Hello world");
        System.out.println(i+"");
    }

}

package poolmanager.test;

import poolmanager.Task;
import poolmanager.ThreadPoolManager;

public class PoolManagerTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        ThreadPoolManager threadpoolmanager = new ThreadPoolManager("SimpleThreadPoll");
        threadpoolmanager.threadPoolStart();
        Task newTask = new TestTask(1);
        threadpoolmanager.addTask(newTask);
         newTask = new TestTask(2);
        threadpoolmanager.addTask(newTask);
         newTask = new TestTask(3);
        threadpoolmanager.addTask(newTask);
         newTask = new TestTask(4);
        threadpoolmanager.addTask(newTask);
         newTask = new TestTask(5);
        threadpoolmanager.addTask(newTask);
         newTask = new TestTask(6);
        threadpoolmanager.addTask(newTask);
        //threadpoolmanager.threadPoolEnd();

    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java线程池实现原理主要涉及以下几个关键组件: 1. 任务队列(Task Queue):用于存储待执行的任务。线程池的线程从任务队列获取任务并执行。 2. 线程池管理器(ThreadPool Manager):负责创建、管理和销毁线程池。它会根据配置的参数(如线程池大小、最大线程数、线程空闲时间等)来控制线程池的行为。 3. 线程池(Thread Pool):由一组复用的线程组成。线程池的线程可以重复使用,避免了频繁创建和销毁线程的开销。 4. 工作线程(Worker Thread):线程池的每个线程都是一个工作线程,负责执行从任务队列获取的任务。 线程池实现原理如下: 1. 初始化线程池线程池管理器根据配置参数初始化一定数量的工作线程,并将它们加入线程池。 2. 提交任务:当有任务需要执行时,将任务提交给线程池管理器。 3. 任务队列管理:线程池管理器将任务添加到任务队列。 4. 工作线程执行任务:空闲的工作线程从任务队列获取任务,并执行任务。 5. 监控线程状态:线程池管理器会监控工作线程的状态,如空闲时间、线程池大小等。 6. 线程回收:当线程池的线程空闲时间超过设定的阈值时,线程池管理器可能会销毁一些空闲的线程,以减少资源占用。 Java线程池实现原理可以优化多线程的管理和资源利用,避免了频繁创建和销毁线程的开销,提高了系统的性能和稳定性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值