zoukankan      html  css  js  c++  java
  • Java工作队列和线程池

     

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

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

    解决方案

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

    队列和线程池演示程序

    1.WorkQueue.java

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

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    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是静态变量,因此我们就可以模拟一下,工作队列的一个执行情况。

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    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顺序打印

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    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. }  

    运行结果是:
    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    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在CODE上查看代码片派生到我的代码片
     
    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. }  

    运行结果是:
    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    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入门 (七) 面向对象(三)
    java入门 (七) 面向对象(二)
    java入门 (七) 面向对象(一)
    ajax异步请求,$.each遍历拼接数据
    java入门 (六) 数组(二)
    java入门 (六) 数组(一)
    java入门 (五) 方法
    微信小程序
    776C Molly's Chemicals --- 前缀和
    CF 458C Elections --- 三分|线段树
  • 原文地址:https://www.cnblogs.com/u0mo5/p/4168485.html
Copyright © 2011-2022 走看看