频道直达 - 专题 - 新闻 - 技巧 - 组网 - 开发 - 安全 - web编程 - 图像 - 操作系统 - 数据库 - 教育 - 旅游 - 健康 - 时尚 - 驱动 - 软件 - 游戏 - 多媒体 - ERP - 讨论组

Java语言深入 多线程程序模型研究

来源: 作者: 出处:巧巧读书 2006-10-27 进入讨论组


    以上程序在for循环结构中创建PortProcessor对象,PortProcessor类是线程类,其关键的Socket在public void run()方法中实现。此程序比第一个单线程的程序运行效率提高很多倍,几乎在几秒钟内得出结果。所以可见多线程处理是何等的重要。

程序(java PortScannerMultiThread 10.1.1.100 1 1000)运行结果如下:
The port 25 is opened at 10.1.1.100
The port 42 is opened at 10.1.1.100
The port 88 is opened at 10.1.1.100
...

    仔细对第2个程序分析,不难发现其中的问题:创建的线程个数是不固定的,取决于输入的第二和第三个参数。如果扫描1~100端口,那么主线程就产生100个线程来分别处理;如果扫描1~10000端口,主线程就会产生10000个线程来进行处理。在JVM中创建如此多的线程同样会带来性能上的问题,因为线程的创建和消失都是需要花费系统资源的。所以以上的第二个程序也存在明显的不足。

    所以,我们需要一个确定数量的线程在JVM中运行,这样就需要了解“线程池”(ThreadPool)的概念。线程池在多线程程序设计中是比不可少的,而且初学者不太容易掌握,下面通过对线程池的介绍,结合第3和第4个程序,引出两种常用的线程池模型。

    第一种实现线程池的方法是:创建一个”池“,在”池“中增加要处理的数据对象,然后创建一定数量的线程,这些线程对”池“中的对象进行处理。当”池“是空的时候,每个线程处于等待状态;当往”池“里添加一个对象,通知所有等待的线程来处理(当然一个对象只能有一个线程来处理)。

    第二种方法是:同样创建一个”池“,但是在”池“中放的不是数据对象,而是线程,可以把”池“中的一个个线程比喻成一个个”工人“,当没有任务的时候,”工人“们严阵以待;当给”池“添加一个任务后,”工人“就开始处理并直到处理完成。

    在第3个程序中,定义了List类型的entries作为“池”,这个“池”用来保存需要扫描的端口,List中的元素必须是Object类型,不能用基本数据类型int往池里添加,而需要用使用Integer。在processMethod()方法中,首先就启动一定数量的PortThread线程,同时在while循环中通过entries.add(0, new Integer(port))往“池”里添加对象。在PortThread类的run()方法中通过entry = (Integer)entries.remove(entries.size()-1);取得“池”中的对象,转换成int后传递给Socket构造方法。
    第3个程序如下:
-----------------------------------------------------------------------------------------------------------------------
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

public class PortScanner {
    private List entries = Collections.synchronizedList(new LinkedList());  //这个”池“比较特别
    int numofthreads;
    static int port;
    int beginport;
    int endport;
    InetAddress remote = null;
    
    public boolean isFinished(){
        if(port >= endport){
            return true;
        }else{
            return false;
        }
    }
    
    PortScanner(InetAddress addr, int beginport, int endport, int numofthreads){
        this.remote = addr;
        this.beginport = beginport;
        this.endport = endport;
        this.numofthreads = numofthreads;    
    }
    
    public void processMethod(){
        for(int i = 0; i < numofthreads; i++){          //创建一定数量的线程并运行
            Thread t = new PortThread(remote, entries, this);
            t.start();
        }
        
        port = beginport;
        
        while(true){
            if(entries.size() > numofthreads){
                try{
                    Thread.sleep(1000);      //”池“中的内容太多的话就sleep
                }catch(InterruptedException ex){
                    
                }
                continue;
            }
            
            synchronized(entries){
                if(port > endport) break;
                entries.add(0, new Integer(port));  //往”池“里添加对象,需要使用int对应的Integer类
                entries.notifyAll();
                port++;
            }
        }
    }
    
    public static void main(String[] args) {
        String host = null;
        int beginport = 1;
        int endport = 65535;
        int nThreads = 100;
        try{
            host = args[0];
            beginport = Integer.parseInt(args[1]);
            endport = Integer.parseInt(args[2]);
            nThreads = Integer.parseInt(args[3]);
            if(beginport <= 0 || endport >= 65536 || beginport > endport){
                throw new Exception("Port is illegal");
            }
        }catch(Exception e){
            System.out.println("Usage: java PortScannerSingleThread host beginport endport nThreads");
            System.exit(0);
        }
        
        try{
            PortScanner scanner = new PortScanner(InetAddress.getByName(host), beginport, endport, nThreads);
            scanner.processMethod();
        }catch(UnknownHostException ex){
        }    
    }
}

class PortThread extends Thread{
    private InetAddress remote;
    private List entries;
    PortScanner scanner;
    
    PortThread(InetAddress add, List entries, PortScanner scanner){
        this.remote = add;
        this.entries = entries;
        this.scanner = scanner;
    }
            
    public void run(){
        Integer entry;
        while(true){
            synchronized(entries){
                while(entries.size() == 0){
                    if(scanner.isFinished()) return;
                    try{
                        entries.wait();           //”池“里没内容就只能等了
                    }catch(InterruptedException ex){
                    }
                }
                entry = (Integer)entries.remove(entries.size()-1);  //把”池“里的东西拿出来进行处理
            }
            
            Socket s = null;
            
            try{
                s = new Socket(remote, entry.intValue());
                System.out.println("The port of " + entry.toString() + " of the remote " + remote +" is opened.");
            
            }catch(IOException e){
            }finally{
                try{
                    if(s != null) s.close();
                }catch(IOException e){
                    
                }
            }
        }
    }
}

收藏地址:http://www.qqread.com/java/2006/10/w255460.html 更多文章 更多内容请看Java环境安装配置Java编程开发手册Java线程专题,或进入讨论组讨论。
收藏此文】【 】【打印】【关闭
相关图文阅读
频道图文推荐
健 康 咨 询
时 尚 咨 询
巧巧读书宗旨
相关专题
最新论坛文章
站内各频道最新更新文档
站内最新制作专题
热门关键字导读
Photoshop教 程照片处理 照片制作 PS快捷键 抠图
计 算 机 故 障XP系统修复
艺 术 与 设 计设计 流媒体 设计欣赏 边框
计 算 机 安 全ARP
站内频道文章精选
巧巧电脑频道编辑信箱  告诉我们您想看的专题或文章