Java工作队列和线程池

分类: 【java】2013-11-21 20:29 917人阅读 评论(3) 收藏 举报

背景
   最近的需要做一个与设备通信的web项目。当然,我们需要写好与设备之间的通信协议(socket)。大致的时序逻辑时:当用户用浏览器点击页面某一控件后,它就向后台发送一个post请求,后台解析前台发送的参数,然后封装成相应的帧格式,然后与设备进行通信,设备接到指令后,完成相应的功能,然后将数据信息返回给后台服务器,后台服务器将这些返回的数据组织好,一方面返回给前台页面,一方面将数据存储到数据库中。
问题:
1.由于通信设备只允许一个socket与它通信,因此,所有的用户都需要共用一个socket,所以,在某一时刻,不能有2个用户同时使用socket

2.当很多条相同的指令以较短的时间间隔(1s左右)发送到通信设备时,通信设备只响应第一条,其他的不予响应。

解决方案

针对上述问题,我们就会想到通过使用队列和线程池来解决以上问题。我们可以将所有用户的指令依次放入队列中,线程池中只允许一个线程运行,而且线程执行完之后,还可以休眠一段时间,等通信设备反应过来的时候,再依次执行队列中的指令。

队列和线程池演示程序

1.WorkQueue.java

该类实现了队列和线程池,详见如下

[java] view plaincopy

  1. /*
  2. * $filename: WorkQueue.java,v $
  3. * $Date: 2013-11-20  $
  4. * Copyright (C) ZhengHaibo, Inc. All rights reserved.
  5. * This software is Made by Zhenghaibo.
  6. */
  7. package edu.njupt.zhb;
  8. import java.util.LinkedList;
  9. /*
  10. *@author: ZhengHaibo
  11. *web:     http://blog.csdn.net/nuptboyzhb
  12. *mail:    [email protected]
  13. *2013-11-20  Nanjing,njupt,China
  14. *References:http://www.ibm.com/developerworks/java/library/j-jtp0730/index.html
  15. */
  16. public class WorkQueue
  17. {
  18. private final int nThreads;//同时最多执行的线程个数
  19. private final PoolWorker[] threads;//线程池
  20. private final LinkedList queue;//线程队列
  21. public WorkQueue(int nThreads)
  22. {
  23. this.nThreads = nThreads;
  24. queue = new LinkedList();
  25. threads = new PoolWorker[nThreads];
  26. for (int i=0; i<nThreads; i++) {
  27. threads[i] = new PoolWorker();
  28. threads[i].start();
  29. }
  30. }
  31. public void execute(Runnable r) {
  32. synchronized(queue) {
  33. queue.addLast(r);
  34. queue.notify();
  35. }
  36. }
  37. private class PoolWorker extends Thread {
  38. public void run() {
  39. Runnable r;
  40. while (true) {
  41. synchronized(queue) {
  42. while (queue.isEmpty()) {
  43. try
  44. {
  45. queue.wait();
  46. }
  47. catch (InterruptedException ignored)
  48. {
  49. }
  50. }
  51. r = (Runnable) queue.removeFirst();
  52. }
  53. // If we don‘t catch RuntimeException,
  54. // the pool could leak threads
  55. try {
  56. r.run();
  57. }
  58. catch (RuntimeException e) {
  59. // You might want to log something here
  60. e.printStackTrace();
  61. }
  62. }
  63. }
  64. }
  65. }

2.WorkThread.java

这是我们的工作线程,在这个Demo中,工作线程只做一件事:将number的值加1,然后休眠,最后打印一下当前number的值。由于number是静态变量,因此我们就可以模拟一下,工作队列的一个执行情况。

[java] view plaincopy

  1. /*
  2. * $filename: WorkThread.java,v $
  3. * $Date: 2013-11-20  $
  4. * Copyright (C) ZhengHaibo, Inc. All rights reserved.
  5. * This software is Made by Zhenghaibo.
  6. */
  7. package edu.njupt.zhb;
  8. /*
  9. *@author: ZhengHaibo
  10. *web:     http://blog.csdn.net/nuptboyzhb
  11. *mail:    [email protected]
  12. *2013-11-20  Nanjing,njupt,China
  13. */
  14. public class WorkThread extends Thread{
  15. public static int number = 0;
  16. @Override
  17. public void run() {
  18. // TODO Auto-generated method stub
  19. try {
  20. number = number + 1;
  21. Thread.sleep(100);
  22. System.out.println("number = "+number);
  23. } catch (Exception e) {
  24. // TODO Auto-generated catch block
  25. e.printStackTrace();
  26. }
  27. }
  28. }

3.测试案例1

我们的线程池只允许一个线程同时执行,这样的结果是:打印number的值是从1-10顺序打印

[java] view plaincopy

  1. /*
  2. * $filename: TestMain.java,v $
  3. * $Date: 2013-11-20  $
  4. * Copyright (C) ZhengHaibo, Inc. All rights reserved.
  5. * This software is Made by Zhenghaibo.
  6. */
  7. package edu.njupt.zhb;
  8. import java.util.ArrayList;
  9. import java.util.List;
  10. /*
  11. *@author: ZhengHaibo
  12. *web:     http://blog.csdn.net/nuptboyzhb
  13. *mail:    [email protected]
  14. *2013-11-20  Nanjing,njupt,China
  15. */
  16. public class TestMain {
  17. /**
  18. * @param args
  19. */
  20. public static void main(String[] args) {
  21. // TODO Auto-generated method stub
  22. WorkQueue workQueue = new WorkQueue(1);//只允许同时运行1个线程
  23. for (int i = 0; i < 10; i++) {
  24. WorkThread wThread = new WorkThread();
  25. workQueue.execute(wThread);
  26. }
  27. }
  28. }

运行结果是:

[java] view plaincopy

  1. number = 1
  2. number = 2
  3. number = 3
  4. number = 4
  5. number = 5
  6. number = 6
  7. number = 7
  8. number = 8
  9. number = 9
  10. number = 10

4.测试案例2

线程池中允许同时最多有5个线程一起执行

[java] view plaincopy

  1. /*
  2. * $filename: TestMain.java,v $
  3. * $Date: 2013-11-20  $
  4. * Copyright (C) ZhengHaibo, Inc. All rights reserved.
  5. * This software is Made by Zhenghaibo.
  6. */
  7. package edu.njupt.zhb;
  8. import java.util.ArrayList;
  9. import java.util.List;
  10. /*
  11. *@author: ZhengHaibo
  12. *web:     http://blog.csdn.net/nuptboyzhb
  13. *mail:    [email protected]
  14. *2013-11-20  Nanjing,njupt,China
  15. */
  16. public class TestMain {
  17. /**
  18. * @param args
  19. */
  20. public static void main(String[] args) {
  21. // TODO Auto-generated method stub
  22. WorkQueue wQueue = new WorkQueue(5);//允许同时运行5个线程
  23. for (int i = 0; i < 10; i++) {
  24. WorkThread wThread = new WorkThread();
  25. wQueue.execute(wThread);
  26. }
  27. }
  28. }

运行结果是:

[java] view plaincopy

  1. number = 5
  2. number = 5
  3. number = 5
  4. number = 5
  5. number = 5
  6. number = 10
  7. number = 10
  8. number = 10
  9. number = 10
  10. number = 10

在某些场合中,如果能够承受100个线程同时运行,那么我们就将workqueue线程池的大小设成100,当线程超过100时,就将线程放入队列queue中,等有一些线程执行结束后,依次执行队列中的线程,一直执行到对列为空时,线程池中的100个线程都在等待新的任务加入。

未经允许不得用于商业目的

时间: 2025-01-14 11:28:26

Java工作队列和线程池的相关文章

JAVA多线程(三) 线程池和锁的深度化

github演示代码地址:https://github.com/showkawa/springBoot_2017/tree/master/spb-demo/src/main/java/com/kawa/thread 1.线程池 1.1 线程池是什么 Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序都可以使用线程池.在开发过程中,合理地使用线程池能够带来3个好处. 第一:降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗. 第二:提高响应速度.当任务

java并发包&amp;线程池原理分析&amp;锁的深度化

      java并发包&线程池原理分析&锁的深度化 并发包 同步容器类 Vector与ArrayList区别 1.ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问.数组的缺点是每个元素之间不能有间隔,当数组大小不满足时需要增加存储能力,就要讲已经有数组的数据复制到新的存储空间中.当从ArrayList的中间位置插入或者删除元素时,需要对数组进行复制.移动.代价比较高.因此,它适合随机查找和遍历,不适合插入和删除. 2.Vector与Arra

《Java并发编程的艺术》 第9章 Java中的线程池

第9章 Java中的线程池 在开发过程中,合理地使用线程池能带来3个好处: 降低资源消耗.通过重复利用已创建的线程 降低线程创建和销毁造成的消耗. 提高响应速度.当任务到达时,任务可以不需要等到线程创建就能立即执行. 提高线程的可管理性.线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一分配.调优和监控. 9.1 线程池的实现原理 当提交一个新任务到线程池时,线程池的处理流程如下: 1)线程池判断核心线程池里的线程是否都在执行任务.如果不是,则创建

Java四种线程池newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor

介绍new Thread的弊端及Java四种线程池的使用,对Android同样适用.本文是基础篇,后面会分享下线程池一些高级功能. 1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? Java new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub } }).start(); 1 2 3 4 5 6 7 new Thread(new

Java四种线程池

Java四种线程池newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor 时间:2015-10-20 22:37:40      阅读:8762      评论:0      收藏:0      [点我收藏+] 介绍new Thread的弊端及Java四种线程池的使用,对Android同样适用.本文是基础篇,后面会分享下线程池一些高级功能. 1.new Thread的弊端执行一个异

Java中的线程池

综述 在我们的开发中经常会使用到多线程.例如在Android中,由于主线程的诸多限制,像网络请求等一些耗时的操作我们必须在子线程中运行.我们往往会通过new Thread来开启一个子线程,待子线程操作完成以后通过Handler切换到主线程中运行.这么以来我们无法管理我们所创建的子线程,并且无限制的创建子线程,它们相互之间竞争,很有可能由于占用过多资源而导致死机或者OOM.所以在Java中为我们提供了线程池来管理我们所创建的线程. 线程池的使用 采用线程池的好处 在这里我们首先来说一下采用线程池的

java笔记--使用线程池优化多线程编程

使用线程池优化多线程编程 认识线程池 在Java中,所有的对象都是需要通过new操作符来创建的,如果创建大量短生命周期的对象,将会使得整个程序的性能非常的低下.这种时候就需要用到了池的技术,比如数据库连接池,线程池等. 在java1.5之后,java自带了线程池,在util包下新增了concurrent包,这个包主要作用就是介绍java线程和线程池如何使用的. 在包java.util.concurrent下的 Executors类中定义了Executor.ExecutorService.Sche

java android ExecutorService 线程池解析

ExecutorService: 它也是一个接口,它扩展自Executor接口,Executor接口更像一个抽象的命令模式,仅有一个方法:execute(runnable);Executor接口简单,可是非常重要,重要在这样的设计的模式上..Java5以后,通过Executor来启动线程比用Thread的start()更好.在新特征中,能够非常easy控制线程的启动.运行和关闭过程,还能够非常easy使用线程池的特性. 几种不同的ExecutorService线程池对象 1.newCachedT

Java实现的 线程池

由于最近开始学习java,用到了线程池,按照之前c++的写法写出此java版的线程池 TaskRunnale实现相关任务的接口,具体要实现什么任务在相应的run函数中实现. package threadpool; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.List; import java.util.Queue; class TaskRunnale implements Runnable {