使用nio进行并行文件下载,而无需为每个文件下载创建线程 我曾经尝试过一个程序,该程序使用java.nio通过为每个文件下载创建一个线程来并行下载文件。 包com.java.tftp.nio; 导入java.io.File; 导入java.io.FileN

使用nio进行并行文件下载,而无需为每个文件下载创建线程 我曾经尝试过一个程序,该程序使用java.nio通过为每个文件下载创建一个线程来并行下载文件。 包com.java.tftp.nio; 导入java.io.File; 导入java.io.FileN,java,io,nio,java.util.concurrent,Java,Io,Nio,Java.util.concurrent,使用nio进行并行文件下载,而无需为每个文件下载创建线程 我曾经尝试过一个程序,该程序使用java.nio通过为每个文件下载创建一个线程来并行下载文件。 包com.java.tftp.nio; 导入java.io.File; 导入java.io.FileNotFoundException; 导入java.io.FileOutputStream; 导入java.io.IOException; 导入java.io.OutputStream; 导入java.net.InetSocketAddress;

使用nio进行并行文件下载,而无需为每个文件下载创建线程
我曾经尝试过一个程序,该程序使用java.nio通过为每个文件下载创建一个线程来并行下载文件。
包com.java.tftp.nio;
导入java.io.File;
导入java.io.FileNotFoundException;
导入java.io.FileOutputStream;
导入java.io.IOException;
导入java.io.OutputStream;
导入java.net.InetSocketAddress;
导入java.net.SocketAddress;
导入java.nio.ByteBuffer;
导入java.nio.channels.DatagramChannel;
导入java.nio.channels.SelectionKey;
导入java.nio.channels.Selector;
导入java.util.Iterator;
导入java.util.List;
导入java.util.Set;
/**
*此类用于通过从tftp服务器并发下载文件
*正在配置文件名,文件数为。
* 
*@author shirram
* 
*/
公共类TFTP_NIO_客户端{
/**
*目标文件夹
* */
私有字符串destinationFolder;
/**
*要下载的文件名列表
* */
私有列表文件名;
/**
*整数表示要同时下载的文件数
* */
私家车内无办公室下载;
公共TFTP_NIO_客户端(列出文件名、字符串目标文件夹、,
int noOfFilesToDownload){
this.destinationFolder=destinationFolder;
this.fileNames=文件名;
this.noOfFilesToDownload=noOfFilesToDownload;
初始化handlers();
}
/**
*此方法创建线程以注册要处理下载的通道
*同时存档。
* 
*@param nooffilestownload
*-要下载的文件数
*/
私有void初始化句柄(){
对于(int i=0;i字节数组中的文件名。0->表示文件模式结束
*->字节数组“netascii”或“octet”中的字符串
* 
*@param aOpcode
*@param-aMode
*@param aFileName
*@抛出异常
*/
私有void sendRequest(int aOpcode、int aMode、字符串aFileName、,
DatagramChannel aChannel,InetSocketAddress aaAddress)
抛出IOException{
//读取请求包
tftpresequestpacket theRequestPacket=新的tftpresequestpacket();
阿查内尔·森德(
TheRequestPackage.ConstructReadRequestPackage(文件名,aMode),
a地址);
}
/**
*发送TFTP ACK数据包:|操作码|块#|操作码->4->2字节
*块->块编号->2字节
* 
*@param-aBlock
*/
专用ByteBuffer发送包(int aBlockNumber){
//确认包
TFTPAckPacket theAckPacket=新的TFTPAckPacket();
返回ackpacket.getTFTPAckPacket(一个锁号);
}
/**
*此类用于处理来自服务器的并发下载。
* 
* */
公共类SelectorHandler扩展线程{
专用选择器;
私有字符串文件名;
/**
*指示文件完成的标志。
* */
私有布尔值isFileReadFinished=false;
公共选择器处理程序(选择器A选择器,字符串A文件名)
抛出IOException{
this.selector=a选择器;
this.fileName=aFileName;
寄存器通道();
}
私有无效注册表通道()引发IOException{
DatagramChannel theChannel=DatagramChannel.open();
信道配置阻塞(假);
selector.wakeup();
通道寄存器(选择器、选择键、操作读取);
sendRequest(Constants.OP_读取、Constants.ASCII_模式、文件名、,
通道,新的InetSocketAddress(Constants.HOST,
常数(TFTP_端口);
}
@凌驾
公开募捐{
过程();
}
私有无效进程(){
System.out.println(“开始下载“+fileName+”);
File theFile=新文件(目标文件夹
+fileName.substring(fileName.lastIndexOf(“/”);
FileOutputStream offout=null;
试一试{
offout=新文件输出流(theFile);
}catch(filenotfounde异常){
e、 printStackTrace();
}
而(!isFileReadFinished){
试一试{
if(selector.select()==0){
试一试{
//引入sleep 2sec是因为选择器是
//线程安全,但密钥不是线程安全的
《睡眠》(2000年);
}捕捉(中断异常e){
继续;
}
继续;
}
设置Set=selector.selectedKeys();
迭代器theSelectedKeys=theSet.Iterator();
已同步(选定键){
while(SelectedKeys.hasNext()){
SelectionKey theKey=theSelectedKeys.next();
选择的键。删除();
if(key.isReadable()){
isFileReadFinished=read(键,offout,
文件名);
如果(!isFileReadFinished){
key.interesttops(选择key.OP_READ);
}
I have tried a program which download files parallely using java.nio by creating a thread per file download.

    package com.java.tftp.nio;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * This class is used to download files concurrently from tftp server by
 * configuring the filenames, no of files.
 * 
 * @author SHRIRAM
 * 
 */
public class TFTP_NIO_Client {

    /**
     * destination folder
     * */
    private String destinationFolder;

    /**
     * list of files names to download
     * */
    private List<String> fileNames;
    /**
     * integer indicates the number of files to download concurrently
     * */
    private int noOfFilesToDownload;

    public TFTP_NIO_Client(List<String> fileNames, String destinationFolder,
            int noOfFilesToDownload) {
        this.destinationFolder = destinationFolder;
        this.fileNames = fileNames;
        this.noOfFilesToDownload = noOfFilesToDownload;
        initializeHandlers();
    }

    /**
     * This method creates threads to register the channel to process download
     * files concurrently.
     * 
     * @param noOfFilesToDownload
     *            - no of files to download
     */
    private void initializeHandlers() {
        for (int i = 0; i < noOfFilesToDownload; i++) {
            try {
                Selector aSelector = Selector.open();
                SelectorHandler theSelectionHandler = new SelectorHandler(
                        aSelector, fileNames.get(i));
                theSelectionHandler.start();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * Setup RRQ/WRQ packet Packet : | Opcode | FileName | 0 | mode | 0 |
     * Filename -> Filename in array of bytes. 0 -> indicates end of file mode
     * -> string in byte array 'netascii' or 'octet'
     * 
     * @param aOpcode
     * @param aMode
     * @param aFileName
     * @throws IOException
     */
    private void sendRequest(int aOpcode, int aMode, String aFileName,
            DatagramChannel aChannel, InetSocketAddress aAddress)
            throws IOException {
        // Read request packet
        TFTPReadRequestPacket theRequestPacket = new TFTPReadRequestPacket();
        aChannel.send(
                theRequestPacket.constructReadRequestPacket(aFileName, aMode),
                aAddress);
    }

    /**
     * sends TFTP ACK Packet Packet : | opcode | Block# | opcode -> 4 -> 2 bytes
     * Block -> block number -> 2bytes
     * 
     * @param aBlock
     */
    private ByteBuffer sendAckPacket(int aBlockNumber) {
        // acknowledge packet
        TFTPAckPacket theAckPacket = new TFTPAckPacket();
        return theAckPacket.getTFTPAckPacket(aBlockNumber);
    }

    /**
     * This class is used to handle concurrent downloads from the server.
     * 
     * */
    public class SelectorHandler extends Thread {
        private Selector selector;
        private String fileName;

        /**
         * flag to indicate the file completion.
         * */
        private boolean isFileReadFinished = false;

        public SelectorHandler(Selector aSelector, String aFileName)
                throws IOException {
            this.selector = aSelector;
            this.fileName = aFileName;
            registerChannel();
        }

        private void registerChannel() throws IOException {
            DatagramChannel theChannel = DatagramChannel.open();
            theChannel.configureBlocking(false);
            selector.wakeup();
            theChannel.register(selector, SelectionKey.OP_READ);
            sendRequest(Constants.OP_READ, Constants.ASCII_MODE, fileName,
                    theChannel, new InetSocketAddress(Constants.HOST,
                            Constants.TFTP_PORT));
        }

        @Override
        public void run() {
            process();
        }

        private void process() {
            System.out.println("Download started for " + fileName + "  ");
            File theFile = new File(destinationFolder
                    + fileName.substring(fileName.lastIndexOf("/")));
            FileOutputStream theFout = null;
            try {
                theFout = new FileOutputStream(theFile);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }

            while (!isFileReadFinished) {
                try {
                    if (selector.select() == 0) {
                        try {
                            // sleep 2sec was introduced because selector is
                            // thread safe but keys are not thread safe
                            Thread.sleep(2000);
                        } catch (InterruptedException e) {
                            continue;
                        }
                        continue;
                    }
                    Set<SelectionKey> theSet = selector.selectedKeys();
                    Iterator<SelectionKey> theSelectedKeys = theSet.iterator();
                    synchronized (theSelectedKeys) {
                        while (theSelectedKeys.hasNext()) {
                            SelectionKey theKey = theSelectedKeys.next();
                            theSelectedKeys.remove();
                            if (theKey.isReadable()) {
                                isFileReadFinished = read(theKey, theFout,
                                        fileName);
                                if (!isFileReadFinished) {
                                    theKey.interestOps(SelectionKey.OP_READ);
                                }
                            } else if (theKey.isWritable()) {
                                // there is no implementation for file write to
                                // server.
                                theKey.interestOps(SelectionKey.OP_READ);
                            }
                        }
                    }
                } catch (IOException ie) {
                    ie.printStackTrace();
                }
            }
            System.out.println("Download finished for " + fileName);
            try {
                if (selector.isOpen()) {
                    selector.close();
                }
                if (theFout != null) {
                    theFout.close();
                }
            } catch (IOException ie) {

            }
        }
    }

    /**
     * @param aKey
     *            registered key for the selector
     * @param aOutStream
     *            - file output stream to write the file contents.
     * @return boolean
     * @throws IOException
     */
    private boolean read(SelectionKey aKey, OutputStream aOutStream,
            String aFileName) throws IOException {
        DatagramChannel theChannel = (DatagramChannel) aKey.channel();

        // data packet
        TFTPDataPacket theDataPacket = new TFTPDataPacket();
        ByteBuffer theReceivedBuffer = theDataPacket.constructTFTPDataPacket();
        SocketAddress theSocketAddress = theChannel.receive(theReceivedBuffer);
        theReceivedBuffer.flip();
        byte[] theBuffer = theReceivedBuffer.array();
        byte[] theDataBuffer = theDataPacket.getDataBlock();
        if (theDataPacket.getOpCode() == Constants.OP_DATA) {
            int theLimit = theDataPacket.getLimit();
            // checks the limit of the buffer because a packet with data less
            // than 512 bytes of content signals that it is the last packet in
            // transmission for this particular file
            if (theLimit != Constants.MAX_BUFFER_SIZE
                    && theLimit < Constants.MAX_BUFFER_SIZE) {
                byte[] theLastBlock = new byte[theLimit];
                System.arraycopy(theBuffer, 0, theLastBlock, 0, theLimit);
                // writes the lastblock
                aOutStream.write(theLastBlock);

                // sends an acknowledgment to the server using TFTP packet
                // block number
                theChannel
                        .send(sendAckPacket((((theBuffer[2] & 0xff) << 8) | (theBuffer[3] & 0xff))),
                                theSocketAddress);
                if (theChannel.isOpen()) {
                    theChannel.close();
                }
                return true;
            } else {
                aOutStream.write(theDataBuffer);
                // sends an acknowledgment to the server using TFTP packet
                // block number
                theChannel
                        .send(sendAckPacket((((theBuffer[2] & 0xff) << 8) | (theBuffer[3] & 0xff))),
                                theSocketAddress);
                return false;
            }
        } else if (Integer.valueOf(theBuffer[1]) == Constants.OP_ERROR) {
            System.out.println("File : " + aFileName + "  not found  ");
            handleError(theReceivedBuffer);
        }
        return false;
    }

    /**
     * This method handles the error packet received from Server.
     * 
     * @param aBuffer
     */
    private void handleError(ByteBuffer aBuffer) {

        // Error packet
        new TFTPErrorPacket(aBuffer);
    }
}

    Is it possible to download multiple files in parallel using java.nio by not creating a thread per file download? If yes can anybody suggest a solution to proceed further.