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

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

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

    解决方案

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

    队列和线程池演示程序

    1.WorkQueue.java

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

    /*
     * $filename: WorkQueue.java,v $
     * $Date: 2013-11-20  $
     * Copyright (C) ZhengHaibo, Inc. All rights reserved.
     * This software is Made by Zhenghaibo.
     */
    package edu.njupt.zhb;
    
    import java.util.LinkedList;
    
    /*
     *@author: ZhengHaibo  
     *web:     http://blog.csdn.net/nuptboyzhb
     *mail:    zhb931706659@126.com
     *2013-11-20  Nanjing,njupt,China
     *References:http://www.ibm.com/developerworks/java/library/j-jtp0730/index.html
     */
    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
                    	e.printStackTrace();
                    }
                }
            }
        }
    }
    


    2.WorkThread.java 

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

    /*
     * $filename: WorkThread.java,v $
     * $Date: 2013-11-20  $
     * Copyright (C) ZhengHaibo, Inc. All rights reserved.
     * This software is Made by Zhenghaibo.
     */
    package edu.njupt.zhb;
    /*
     *@author: ZhengHaibo  
     *web:     http://blog.csdn.net/nuptboyzhb
     *mail:    zhb931706659@126.com
     *2013-11-20  Nanjing,njupt,China
     */
    public class WorkThread extends Thread{
        public static int number = 0;
    	@Override
    	public void run() {
    		// TODO Auto-generated method stub
    		try {
    			number = number + 1;
    			Thread.sleep(100);
    			System.out.println("number = "+number);
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    	
    }
    


    3.测试案例1

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

    /*
     * $filename: TestMain.java,v $
     * $Date: 2013-11-20  $
     * Copyright (C) ZhengHaibo, Inc. All rights reserved.
     * This software is Made by Zhenghaibo.
     */
    package edu.njupt.zhb;
    
    import java.util.ArrayList;
    import java.util.List;
    /*
     *@author: ZhengHaibo  
     *web:     http://blog.csdn.net/nuptboyzhb
     *mail:    zhb931706659@126.com
     *2013-11-20  Nanjing,njupt,China
     */
    public class TestMain {
    
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		WorkQueue workQueue = new WorkQueue(1);//只允许同时运行1个线程
    		for (int i = 0; i < 10; i++) {
    			WorkThread wThread = new WorkThread();
    			workQueue.execute(wThread);
    		}
    	}
    
    }
    


    运行结果是:

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


    4.测试案例2 

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

    /*
     * $filename: TestMain.java,v $
     * $Date: 2013-11-20  $
     * Copyright (C) ZhengHaibo, Inc. All rights reserved.
     * This software is Made by Zhenghaibo.
     */
    package edu.njupt.zhb;
    
    import java.util.ArrayList;
    import java.util.List;
    /*
     *@author: ZhengHaibo  
     *web:     http://blog.csdn.net/nuptboyzhb
     *mail:    zhb931706659@126.com
     *2013-11-20  Nanjing,njupt,China
     */
    public class TestMain {
    
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		WorkQueue wQueue = new WorkQueue(5);//允许同时运行5个线程
    		for (int i = 0; i < 10; i++) {
    			WorkThread wThread = new WorkThread();
    			wQueue.execute(wThread);
    		}
    	}
    
    }
    


    运行结果是:

    number = 5
    number = 5
    number = 5
    number = 5
    number = 5
    number = 10
    number = 10
    number = 10
    number = 10
    number = 10


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


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


  • 相关阅读:
    从0开始学习 GitHub 系列之「02.加入 GitHub」
    从0开始学习 GitHub 系列之「01.初识 GitHub
    用Redis轻松实现秒杀系统
    算法之美
    Android窗口管理服务WindowManagerService显示Activity组件的启动窗口(Starting Window)的过程分析
    6)django-示例(fbv)
    5)django-模板
    4)django-视图view
    3)django-路由系统url
    2)django-请求生命周期
  • 原文地址:https://www.cnblogs.com/fuhaots2009/p/3437090.html
Copyright © 2011-2022 走看看