`
gaoyuntao2005
  • 浏览: 312484 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

ava并发学习之二:线程池

阅读更多

第二步,是实现一个线程池 

因为之前看书的时候留了个心眼,看线程池相关的内容的时候特意没去研究JDK的实现 
因为学跟做不是一码事,写一个线程池,算是给自己看完并发实践这书的一个练习吧 

废话不多说,练习开始 

首先,整理一下要实现的功能,或者说要注意的元素 
1.实现Executor接口 
2.实现一个等待队列(可否配置,优先级等) 
3.是否需要预启动线程(可否配置) 
4.执行开始前,结束后,需要留接口 
5.Runable在任务中的存放形式 
6.线程的启动,唤醒 
7.线程池的关闭(优雅地结束),需要线程提供中断,线程池提供给使用者的提示,线程池返回取消线程等 
8.线程队列(空闲队列?) 
9.取空闲线程算法(任务入队时?线程执行一个任务结束时?) 
10.将所有需要同步的地方尽量使用非阻塞算法(通过侦察,更新一个原子变量实现) 
11.减少线程切换开销(轮询是否有任务,n微秒后再进入等待) 

暂时就考虑到这些,剩下的以后再补 

总的来说,计划写n个版本(毕竟是第二次动手,写一个庞大的需要细致考虑的东西功力还差远呢,只能从最简单的,最方便的实现开始,然后慢慢加强) 

测试先行: 

Java代码  收藏代码
  1. public static void main(String[] args) throws InterruptedException  
  2. {  
  3.     testEasyRunnableThreadPool(new ThreadPoolTest1(10), 1000010);  
  4.     testEasyRunnableThreadPool(Executors.newFixedThreadPool(10), 1000010);  
  5. }  
  6.   
  7. /** 
  8.  * 一个产生随机数的方法,防止jvm优化 
  9.  * @param seed 
  10.  * @return 
  11.  */  
  12. static int getRandomNum(int seed)  
  13. {  
  14.     seed ^= (seed << 6);  
  15.     seed ^= (seed >>> 21);  
  16.     seed ^= (seed << 7);  
  17.     return seed;  
  18. }  
  19.   
  20. /** 
  21.  * 执行一个简单的计算,只占用cpu,没有io和其他阻塞的方法 
  22.  * @param pool 
  23.  * @param tryTime 
  24.  * @param threadNum 
  25.  * @throws InterruptedException 
  26.  */  
  27. static void testEasyRunnableThreadPool(Executor pool,int tryTime,int threadNum) throws InterruptedException  
  28. {  
  29.     //construct runnable  
  30.     Runnable command = new Runnable() {           
  31.         public void run() {  
  32.             final int addTime = 1000000;  
  33.             long sum = 0;  
  34.             int temp = this.hashCode() ^ (int)System.currentTimeMillis();  
  35.             for(int i = 0;i<addTime;i++)  
  36.             {  
  37.                 sum += (temp = getRandomNum(temp));  
  38.             }                 
  39.         }  
  40.     };        
  41.     testThreadPool(tryTime, pool, command);  
  42. }  
  43.   
  44. /** 
  45.  *  
  46.  * @param tryNum  
  47.  * @param pool 
  48.  * @param commandList 
  49.  * @throws InterruptedException 
  50.  */  
  51. static void testThreadPool(int tryNum,Executor pool,final Runnable command) throws InterruptedException  
  52. {  
  53.     final CountDownLatch latch = new CountDownLatch(tryNum);  
  54.     Runnable wrapper = new Runnable() {           
  55.         public void run() {  
  56.             command.run();  
  57.             //想测试并发,在并发中加入适当的同步操作是无法避免的,只能减少  
  58.             //,在这,只是做了一个简单的countdown,影响不大  
  59.             latch.countDown();  
  60.         }  
  61.     };  
  62.     long startTime = System.nanoTime();  
  63.     for(int i = 0;i<tryNum;i++)  
  64.     {  
  65.         pool.execute(wrapper);  
  66.     }         
  67.     latch.await();  
  68.     long endTime = System.nanoTime();  
  69.     System.out.println(endTime-startTime);  
  70. }  



线程池代码: 
第一版本的目标很简单,只要能跑,没死锁,就是完胜 
可惜结果很让人绝望~ 
写完了,调了近3个小时,仍然没发现问题,最后加了一堆输出,又加了多个锁,终于勉勉强强跑起来了…… 
并发的调试真难,debug完全没用,看输出又看不出什么来,只能是一遍一遍地检查代码,写下一个版本前先找点资料,研究下调试方法吧 
后来发现错误是一个简单的i++…… 
Java代码  收藏代码
  1. public class ThreadPoolTest1 implements Executor {  
  2.     //等待队列  
  3.     Queue<Runnable> waitingQueue = null;  
  4.       
  5.     ConcurrentLinkedQueue<ThreadNode> freeThread;  
  6.     //相当于一个freeThread的状态,根据状态决定行为,原则上将freeThread.size()+busyThreadsNum=MAXTHREADNUM  
  7.     private AtomicInteger busyThreadsNum = new AtomicInteger(0);  
  8.     //最大线程数  
  9.     final int MAXTHREADNUM;  
  10.       
  11.     public ThreadPoolTest1 (int threadNum)  
  12.     {  
  13.         this.MAXTHREADNUM = threadNum;  
  14.         init(MAXTHREADNUM,new ConcurrentLinkedQueue<Runnable>());  
  15.     }     
  16.   
  17.     private void init(int threadNum,ConcurrentLinkedQueue<Runnable> queue)  
  18.     {  
  19.         freeThread = new ConcurrentLinkedQueue<ThreadNode>();  
  20.         waitingQueue = queue;  
  21.         //初始化空线程,一开始不是这样实现的,后来发现一堆问题,暂时只能先加锁,无论怎么样,跑起来再说把  
  22.         synchronized(this)  
  23.         {  
  24.             for(int i = 0;i<threadNum;i++)  
  25.             {  
  26.                 ThreadNode node = new ThreadNode();  
  27.                 busyThreadsNum.incrementAndGet();                 
  28.                 node.start();  
  29.             }  
  30.         }  
  31.     }  
  32.       
  33.     private synchronized void threadExecute(Runnable command)  
  34.     {  
  35.         //用了个挺弱智的非阻塞算法  
  36.         for(;;)  
  37.         {  
  38.             //得到开始的值  
  39.             int expect = busyThreadsNum.get();  
  40.             if(expect == MAXTHREADNUM)  
  41.             {  
  42.                 waitingQueue.add(command);  
  43.                 return;  
  44.             }  
  45.             else  
  46.             {  
  47.                 //比较并设置,如果失败,重来  
  48.                 if(busyThreadsNum.compareAndSet(expect, ++expect))//之前写的是expect++,检查了n久,硬是看不出啥问题,只能怪自己天资愚鲁吧  
  49.                 {  
  50.                     ThreadNode t = freeThread.remove();  
  51.                     t.setCommand(command);  
  52.                     synchronized(t)  
  53.                     {t.notify();}  
  54.                     return;  
  55.                 }  
  56.                 else  
  57.                     continue;  
  58. font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color:
    分享到:
    评论

相关推荐

    JAVA并发编程实践(英文版+中文1-9章)

    本书的中文版稀缺性凸显了其价值,它不仅提供了英文原版,还包含了中文翻译的前九章,对于想要学习并发编程的开发者来说,这是一个宝贵的资源。中英对照阅读不仅可以帮助理解专业术语,还能提高英语阅读能力,尤其是...

    JVM调优总结与ava虚拟机:JVM高级特性与最佳实践(最新第二版)

    6. **并发与多线程**:Java的并发模型基于内存模型,包括volatile、synchronized、原子类(Atomic*)等特性,以及线程池的配置和优化。 7. **JVM参数设置**:理解并掌握-Xms, -Xmx, -XX:NewRatio, -XX:...

    java面试大全[135套java面试题]

    - **并发编程**:线程池、并发容器、并发工具类的使用。 - **性能调优**:内存管理、垃圾收集器的选择、JVM参数调整。 这135套Java面试题覆盖了以上各个方面的知识点,对于Java开发者来说,熟练掌握这些内容不仅...

    成为JۥAVA软件程师需要学哪些参考精选.doc

    - 学习线程池的使用和配置,如ExecutorService。 5. **JAVA反射机制**: - 学习如何在运行时动态获取类信息,创建对象,调用方法。 6. **JAVA注解(Annotation)**: - 了解注解的定义、使用及自定义注解。 7....

    同程旅游2017 校招ava开发工程师.pdf

    3. **并发编程**:由于旅游行业业务的高并发特性,熟悉线程池、锁机制、并发容器(如ConcurrentHashMap)等并发编程技术是非常必要的。 4. **Spring框架**:作为企业级应用的主流框架,Spring的使用是必须的,包括...

    80w字Java面试宝典(非常全)

    ava八股文通常是指Java技术面试中常见的知识点集合,涵盖基础理论、常用框架、进阶技能等内容。以下是概述中可能包含的主要内容: Java基础: 基本语法:数据类型、操作符、控制语句等。 面向对象:封装、继承、多态...

    java面试评价表

    - **改进空间**:反思项目中存在的不足之处及改进方案。 - **三方系统设计**:讨论在设计涉及多方交互的系统时,接口及数据流的设计原则。 #### 十、高级开发与综合题 - **新技能获取**:分享近期学习的新技能或...

    Java-Threads.rar_threads

    这本书的第三版(ava Threads, 3rd Edit.chm)详细介绍了如何在Java应用程序中有效地利用多核处理器,提高程序的性能和响应速度。 在Java中,线程是程序执行的最小单元,它允许一个应用程序同时执行多个任务。通过...

    concurrent_download.rar

    这个Java迷你版迅雷下载器的源码应该包含上述技术的实现,对于学习Java并发编程和网络I/O的开发者来说,这是一个很好的实践案例。通过阅读和分析源码,我们可以深入理解多线程下载的实现细节,以及如何在Java中有效...

    阿里巴巴Java开发手册1.5.0华山版.zip

    3. **并发编程**:手册针对多线程编程给出了指导,如使用并发工具类(如`ConcurrentHashMap`、`BlockingQueue`)而非同步方法,避免过度使用`synchronized`关键字,以及如何正确地使用线程池以提高系统性能。...

    java线程学习

    以上就是Java线程学习的核心知识点,理解并熟练掌握这些内容,能够帮助开发者编写高效、稳定的多线程程序。在实际开发中,还需要根据具体需求灵活应用,注意避免线程安全问题,确保程序的正确性和性能。

    amareya java 协程

    - 协程的并发度取决于可用的CPU核心数量,而非系统级别的线程池。 - 调度策略和并发模型需要根据具体应用场景进行选择和调整。 - 使用Amareya库时,应遵循其文档和最佳实践,确保正确处理协程间的同步和异常。 总的...

    jmul:(J)ava(m)其他(u)实用程序(l)图书馆

    6. **线程与并发**:JMUL 提供了一些高级的线程和并发工具,如线程池管理、同步机制,帮助开发者更好地控制多线程环境下的程序执行。 7. **数学计算**:对于需要进行数学运算的场景,JMUL 提供了一些数学函数,包括...

    详细整理Java面试题,面试题及完整答案.zip

    并发编程是Java的强项,面试题可能涵盖线程同步(synchronized、Lock、volatile)、线程池(ExecutorService、ThreadPoolExecutor)、并发容器(ConcurrentHashMap、BlockingQueue)、死锁、活锁与饥饿问题。...

    Android 文件下载功能Java多线程下载功能的例子实例源码.zip

    - 使用`ExecutorService`创建线程池可以有效管理并发线程数量,防止过多线程导致资源浪费或系统不稳定。 7. **Android的异步任务和AsyncTask**: - 虽然在Android 3.0之后,AsyncTask不推荐用于长时间运行的任务...

Global site tag (gtag.js) - Google Analytics