doukk 2012-07-09 16:16
浏览 275
已采纳

请教多线程JAVA问题

需求:

命令队列(存放n个命令,ip 端口 命令ID等信息),通过多线程scoket(线程数是20个).从命令队列里面取出 命令,解析执行。

连接的服务器,连接数是有限制的最大2个连接。所以scoket 必须维持长连接

最多可以有20个线程 连接20个不同IP的机器。但机器是N个。

问题1 怎么在多线程中维持长连接发送 接收数据,相同IP的命令发送接收完后需要断开连接。

  • 写回答

3条回答

  • feizhuzi 2012-07-10 20:45
    关注

    对我的思路作下修改应该能满足你的需求

    [code="java"]
    public class Demo {
    public static void main(String[] args) throws UnknownHostException, IOException {

        //我这里演示4个不同的IP的多任务任务队列
        //已知条件提到20个线程不断开的连接20个IP的机器,那就只能对于某个IP只能连接它的一个端口
        //只是演示一下,当做伪代码看
        Queue<String[]> taskQueue = new LinkedList<String[]>();
    
        List<String[]> list = Arrays.asList(
                new String[]{"192.168.0.2", "2", "laugh"},  
                new String[]{"192.168.0.2", "2", "run"},  
                new String[]{"192.168.0.2", "2", "sing"},  
                new String[]{"192.168.0.3", "3", "run"},  
                new String[]{"192.168.0.3", "3", "sing"},
                new String[]{"192.168.0.4", "4", "laugh"},  
                new String[]{"192.168.0.4", "4", "sing"},
                new String[]{"192.168.0.5", "5", "sing"}
            );
    
        //  < "ip:port", Client连接>
        Map<String, Client> map = new HashMap<String, Client>();
    
        for (String[] strings : list) {
            String ip = strings[0];
            int port = Integer.parseInt(strings[1]);
            String comman = strings[2];
    
            //标识连接某个IP的socket
            String socketKey = ip + ":" + port;
            Client client = map.get(socketKey);
    
            //如果对于这个IP还没发起连接
            if(client == null){
                client = new Client(ip, port);
                map.put(socketKey, client);
            }else{
                client.addTask(comman);
            }
        }
    }
    

    }

    class Client extends Thread{

    private int port;
    private String host;
    private Socket socket;
    private PrintWriter writer;
    private BufferedReader reader;
    private boolean shutdown = false;
    //每个发起的连接都有自己的任务队列
    private Queue<String> taskQueue = new LinkedList<String>();
    
    //一个客户端对应一个socket连接
    public Client(String host, int port) {
        //TODO validate
        this.host = host;
        this.port = port;
    }
    
    @Override
    //这里只用一个线程处理任务,因为对一个IP只能建立一个连接
    public void run() {
        this.socket = new Socket();
        try{
            socket.connect(InetSocketAddress.createUnresolved(host, port));
            reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true);
    
            String task;
            //当还没通知关闭时,线程一直运行(同时连接也保持)
            while(!shutdown){
                //这里要取出队列中的任务,可能取任务的同时
                //外面也传进任务,所以要加上同步块
                synchronized (taskQueue) {
                    //当任务队列一直为空的时候一直循环,知道有任务或者通知关闭
                    while(taskQueue.isEmpty()){
                        if(shutdown){//如果需要关闭客户端,则返回
                            return;
                        }
                        //如果不需要关闭,则等待资源
                        //当队列中增加任务会被唤醒
                        try {
                            taskQueue.wait();
                        }catch (InterruptedException  e) {}
                    }
    
                    //此时任务队列有任务进来
                    task = taskQueue.poll();
                }
    
                //执行任务不需要同步块保护
                execTask(task);
    
            }
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            closeAll();
        }
    }
    
    public void addTask(String command) {
        synchronized (taskQueue) {
            taskQueue.add(command);
            //唤醒等待任务队列资源的当前线程
            taskQueue.notifyAll();
        }
    }
    
    public void execTask (String command) {
        writer.println(command);//当然PrintWriter.println用在网络上有点问题,先不管
    }
    
    class ReadServerInfoThread extends Thread{
        @Override
        public void run() {
            try{
                String line = null;
                while( (line = reader.readLine()) != null ){
                    //打印服务器返回的消息
                    System.out.println(line);
                }
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    public void closeAll() {
        if(writer != null){
            try {
                writer.close();
            } catch (Exception e2) {
            }
        }
        if(reader != null){
            try {
                reader.close();
            } catch (Exception e2) {
            }
        }
        if(socket != null && !socket.isClosed()){
            try {
                socket.close();
            } catch (Exception e2) {
            }
        }
    }
    

    }

    [/code]

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 LiBeAs的带隙等于0.997eV,计算阴离子的N和P
  • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘
  • ¥15 来真人,不要ai!matlab有关常微分方程的问题求解决,
  • ¥15 perl MISA分析p3_in脚本出错
  • ¥15 k8s部署jupyterlab,jupyterlab保存不了文件
  • ¥15 ubuntu虚拟机打包apk错误
  • ¥199 rust编程架构设计的方案 有偿
  • ¥15 回答4f系统的像差计算
  • ¥15 java如何提取出pdf里的文字?
  • ¥100 求三轴之间相互配合画圆以及直线的算法