zoukankan      html  css  js  c++  java
  • jdk线程池主要原理

    本文转自:http://blog.csdn.net/linchengzhi/article/details/7567397

      正常创建一个线程的时候,我们是这样的:new thread(Runnable实现类)。这里,thread是线程,Runnable实现类是业务逻辑,这样线程和业务逻辑紧紧绑定在一起。

    采用线程池来处理的时候,我们动态生成若干个线程存于池中,但是这些线程要执行那些业务逻辑是不知道的,由于业务逻辑个数和具体的逻辑需要用户来指定,这些是变化的,我们需要自己编写并存于linkedList(linkedList便于删除和增加)。

    那线程如何从linkedList中读取一个一个的业务逻辑,比较好的办法就是thread中的run方法来一个while(true)循环,并不断的从linkedList中读取业务逻辑(如:r = (Runnable) queue.removeFirst();),并执行业务逻辑。由于thread中的run方法一上来就写好的,不知道具体的业务逻辑实现类是什么,所以必须使用多态的方式,并传递具体的业务逻辑实现类给基类。

    jdk,为了方便编程并减少接口个数,这个基类就采用runnable,这样线程池执行的时候只需要这样,producerPool.execute(new ThreadPoolTask(task)); ThreadPoolTask实现了runnable接口。

    参考如下代码:

    具有线程池的工作队列:http://www.ibm.com/developerworks/cn/java/j-jtp0730/

    public class WorkQueue
    {
        private final int nThreads;
        private final PoolWorker[] threads;
        private final LinkedList queue;
        public WorkQueue(int nThreads)
        {
            this.nThreads = nThreads;
            queue = new LinkedList();
            threads = new PoolWorker[nThreads];
            for (int i=0; i<nThreads; i++) {
                threads[i] = new PoolWorker();
                threads[i].start();
            }
        }
        public void execute(Runnable r) {
            synchronized(queue) {
                queue.addLast(r);
                queue.notify();
            }
        }
        private class PoolWorker extends Thread {
            public void run() {
                Runnable r;
                while (true) {
                    synchronized(queue) {
                        while (queue.isEmpty()) {
                            try
                            {
                                queue.wait();
                            }
                            catch (InterruptedException ignored)
                            {
                            }
                        }
                        r = (Runnable) queue.removeFirst();
                    }
                    // If we don't catch RuntimeException, 
                    // the pool could leak threads
                    try {
                        r.run();
                    }
                    catch (RuntimeException e) {
                        // You might want to log something here
                    }
                }
            }
        }
    }
    

    还可参考:http://newleague.iteye.com/blog/1124024

    使用jdk线程池代码,已经测试过,可运行:http://fire11.iteye.com/blog/636454

    package cn.simplelife.exercise;

    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;

    public class TestThreadPool {
        private static int produceTaskSleepTime = 2;

        public static void main(String[] args) {
            // 构造一个线程池
            ThreadPoolExecutor producerPool = new ThreadPoolExecutor(1, 1, 0, TimeUnit.SECONDS, new ArrayBlockingQueue(3),
                    new ThreadPoolExecutor.DiscardOldestPolicy());

            // 每隔produceTaskSleepTime的时间向线程池派送一个任务。
            int i = 1;
            while (true) {
                try {
                    Thread.sleep(produceTaskSleepTime);

                    String task = "task@ " + i;
                    System.out.println("put " + task);

                    producerPool.execute(new ThreadPoolTask(task));

                    i++;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    package cn.simplelife.exercise;

    import java.io.Serializable;

    /**
     * 线程池执行的任务
     * 
     * @author hdpan
     */
    public class ThreadPoolTask implements Runnable, Serializable {

        // JDK1.5中,每个实现Serializable接口的类都推荐声明这样的一个ID
        private static final long serialVersionUID = 0;

        private static int consumeTaskSleepTime = 2000;
        private Object threadPoolTaskData;

        ThreadPoolTask(Object tasks) {
            this.threadPoolTaskData = tasks;
        }

        // 每个任务的执行过程,现在是什么都没做,除了print和sleep,:)
        public void run() {
            System.out.println("start .." + threadPoolTaskData);
            try {
                // 便于观察现象,等待一段时间
                Thread.sleep(consumeTaskSleepTime);
            } catch (Exception e) {
                e.printStackTrace();
            }
            threadPoolTaskData = null;
        }
    }

    jdk对线程池做了很好的封装,内有大量同步实现和各种情况的考虑,个人看完源代码,还是觉得用jdk的线程池比较好。

  • 相关阅读:
    SharePoint 2010 获取当前用户的权限
    SharePoint 2010 移除Ribbon菜单中的命令项
    SqlServer2000孤立用户解决方案
    Hello Go!
    XMLHttpRequest对象介绍——1
    Struts 2 简单配置
    asp.net 2.0热贴收藏
    .NET牛人应该知道些什么(转)?
    ASP.net 2.0 中 WebResource.axd 管理资源的一些知识点
    asp.net中的异步页面
  • 原文地址:https://www.cnblogs.com/kmsfan/p/3899327.html
Copyright © 2011-2022 走看看