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

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

解决方案

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

队列和线程池演示程序

1.WorkQueue.java

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

  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.  
  9. import java.util.LinkedList;
  10.  
  11. /*
  12. *@author: ZhengHaibo
  13. *web: http://blog.csdn.net/nuptboyzhb
  14. *mail: zhb931706659@126.com
  15. *2013-11-20 Nanjing,njupt,China
  16. *References:http://www.ibm.com/developerworks/java/library/j-jtp0730/index.html
  17. */
  18. public class WorkQueue
  19. {
  20. private final int nThreads;//同时最多执行的线程个数
  21. private final PoolWorker[] threads;//线程池
  22. private final LinkedList queue;//线程队列
  23.  
  24. public WorkQueue(int nThreads)
  25. {
  26. this.nThreads = nThreads;
  27. queue = new LinkedList();
  28. threads = new PoolWorker[nThreads];
  29.  
  30. for (int i=0; i<nThreads; i++) {
  31. threads[i] = new PoolWorker();
  32. threads[i].start();
  33. }
  34. }
  35.  
  36. public void execute(Runnable r) {
  37. synchronized(queue) {
  38. queue.addLast(r);
  39. queue.notify();
  40. }
  41. }
  42.  
  43. private class PoolWorker extends Thread {
  44. public void run() {
  45. Runnable r;
  46.  
  47. while (true) {
  48. synchronized(queue) {
  49. while (queue.isEmpty()) {
  50. try
  51. {
  52. queue.wait();
  53. }
  54. catch (InterruptedException ignored)
  55. {
  56. }
  57. }
  58.  
  59. r = (Runnable) queue.removeFirst();
  60. }
  61.  
  62. // If we don't catch RuntimeException,
  63. // the pool could leak threads
  64. try {
  65. r.run();
  66. }
  67. catch (RuntimeException e) {
  68. // You might want to log something here
  69. e.printStackTrace();
  70. }
  71. }
  72. }
  73. }
  74. }

2.WorkThread.java

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

  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: zhb931706659@126.com
  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.  
  29. }

3.测试案例1

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

  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.  
  9. import java.util.ArrayList;
  10. import java.util.List;
  11. /*
  12. *@author: ZhengHaibo
  13. *web: http://blog.csdn.net/nuptboyzhb
  14. *mail: zhb931706659@126.com
  15. *2013-11-20 Nanjing,njupt,China
  16. */
  17. public class TestMain {
  18.  
  19. /**
  20. * @param args
  21. */
  22. public static void main(String[] args) {
  23. // TODO Auto-generated method stub
  24. WorkQueue workQueue = new WorkQueue(1);//只允许同时运行1个线程
  25. for (int i = 0; i < 10; i++) {
  26. WorkThread wThread = new WorkThread();
  27. workQueue.execute(wThread);
  28. }
  29. }
  30.  
  31. }

运行结果是:

  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个线程一起执行

  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.  
  9. import java.util.ArrayList;
  10. import java.util.List;
  11. /*
  12. *@author: ZhengHaibo
  13. *web: http://blog.csdn.net/nuptboyzhb
  14. *mail: zhb931706659@126.com
  15. *2013-11-20 Nanjing,njupt,China
  16. */
  17. public class TestMain {
  18.  
  19. /**
  20. * @param args
  21. */
  22. public static void main(String[] args) {
  23. // TODO Auto-generated method stub
  24. WorkQueue wQueue = new WorkQueue(5);//允许同时运行5个线程
  25. for (int i = 0; i < 10; i++) {
  26. WorkThread wThread = new WorkThread();
  27. wQueue.execute(wThread);
  28. }
  29. }
  30.  
  31. }

运行结果是:

  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个线程都在等待新的任务加入。

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

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

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

          java并发包&线程池原理分析&锁的深度化 并发包 同步容器类 Vector与ArrayList区别 1.ArrayList是最常用的List实现类,内部是通过数组实现的, ...

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

    github演示代码地址:https://github.com/showkawa/springBoot_2017/tree/master/spb-demo/spb-brian-query-servic ...

  3. Java并发包——线程池

    Java并发包——线程池 摘要:本文主要学习了Java并发包中的线程池. 部分内容来自以下博客: https://www.cnblogs.com/dolphin0520/p/3932921.html ...

  4. Java学习笔记 线程池使用及详解

    有点笨,参考了好几篇大佬们写的文章才整理出来的笔记.... 字面意思上解释,线程池就是装有线程的池,我们可以把要执行的多线程交给线程池来处理,和连接池的概念一样,通过维护一定数量的线程池来达到多个线程 ...

  5. Java原理领悟-线程池(Executor)

    线程池全面解析 什么是线程池? 很简单,简单看名字就知道是装有线程的池子,我们可以把要执行的多线程交给线程池来处理,和连接池的概念一样,通过维护一定数量的线程池来达到多个线程的复用. 线程池的好处 我 ...

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

    第9章 Java中的线程池 在开发过程中,合理地使用线程池能带来3个好处: 降低资源消耗.通过重复利用已创建的线程 降低线程创建和销毁造成的消耗. 提高响应速度.当任务到达时,任务可以不需要等到线程创 ...

  7. 浅析Java中的线程池

    Java中的线程池 几乎所有需要异步或并发执行任务的程序都可以使用线程池,开发过程中合理使用线程池能够带来以下三个好处: 降低资源消耗 提高响应速度 提高线程的可管理性 1. 线程池的实现原理 当我们 ...

  8. Java多线程与线程池技术

    一.序言 Java多线程编程线程池被广泛使用,甚至成为了标配. 线程池本质是池化技术的应用,和连接池类似,创建连接与关闭连接属于耗时操作,创建线程与销毁线程也属于重操作,为了提高效率,先提前创建好一批 ...

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

    介绍new Thread的弊端及Java四种线程池的使用,对Android同样适用.本文是基础篇,后面会分享下线程池一些高级功能. 1.new Thread的弊端执行一个异步任务你还只是如下new T ...

随机推荐

  1. XML1_XML基础

    1.XML的作用 XML 被设计用来传输和存储数据.所以XML 是不作为的. 2.简单的描述 XML 文档形成一种树结构. XML 文档必须包含根元素.该元素是所有其他元素的父元素.XML 文档中的元 ...

  2. Vcl.FileCtrl.SelectDirectory

    描述:显示一个目录的对话框(属于Delphi) function SelectDirectory(var Directory: string; Options: TSelectDirOpts; Hel ...

  3. LOL(英雄联盟)系统鼠标速度锁定工具

    最近习惯将系统的鼠标速度降低, 而提高鼠标硬件DPI来提升移动准确度, 但是LOL的客户端每次启动进入游戏后就会还原系统鼠标的移动速度, 我把情况反应给腾讯,没想到他们一点都不重视, 建议我只改游戏里 ...

  4. Excel下拉框选项切换行颜色切换

    选择行颜色变化范围 开始-条件格式-新创建规则-"使用公式-" 录入:=$104B="确认" 点击"格式(F)-"->填充,选择填充颜 ...

  5. 解决EXC_BAD_ACCESS错误的一种方法--NSZombieEnabled

    iOS 程序开发时经常用遇到 EXC_BAD_ACCESS 错误导致 Crash,出现这种错误时一般 Xcode 不会给我们太多的信息来定位错误来源,只是在应用 Delegate 上留下像Thread ...

  6. Python读写Redis数据库

    import redis class Database: def __init__(self): self.host = 'localhost' self.port = 6379 def write( ...

  7. [topcoder]IncreasingSubsequences

    http://community.topcoder.com/stat?c=problem_statement&pm=7753&rd=10672 http://community.top ...

  8. Android内存优化之——static使用篇

    在Android开发中,我们经常会使用到static来修饰我们的成员变量,其本意是为了让多个对象共用一份空间,节省内存,或者是使用单例模式,让该类只生产一个实例而在整个app中使用.然而在某些时候不恰 ...

  9. perl 监控数据库用到的数据结构

    [root@yun1 test]# cat a1.pl my $h={'192.168.11.187'=>['root','1234567'], '192.168.5.7' =>['roo ...

  10. C++中new和不new的区别

    我们都知道C++中有三种创建对象的方法,如下: 复制代码代码如下: #include <iostream>using namespace std; class A{private:    ...