生产者与消费者

生产者与消费者模式:

目的:优化系统性能。

如从远程下载文件,并将这些文件解析。

生产者:启一个或多个线程专门从事下载文件,下载ok的文件放进队列queue中。

消费者:启一个或多个线程专门从事解析文件,从队列queue中拿文件解析。

结构如图:

每个线程做自己的事情,当要用到临界资源Queue时,各个线程抢占资源,一旦有一个线程访问Queue,就阻塞(lock)Queue,等这个线程

访问完Queue后方能解锁。

----------------------------------------------------

如从远程下载文件,并将这些文件解析

代码演示:

----------------------------

自写一个xx.properties,里面是一些配置信息。

username=hello
password=hello
hostname=172.17.206.123
port=21
remotedir=/SIMCard_Manager/
downloaddir=E:/test/
errordir=E:/test/error/
downloadnum=10
resolvenum=0

---------------------------

配置信息类:

public class InitData
{
    /**
     * ftp登录名
     */
    public static final String USERNAME;
    
    /**
     * 密码
     */
    public static final String PASSWORD;
    
    /**
     * host
     */
    public static final String HOSTNAME;
    
    /**
     * 端口
     */
    public static final int PORT;
    
    /**
     * ftp端的目录
     */
    public static final String REMOTEDIR;
    
    /**
     * 下载到本地目录
     */
    public static final String DOWNLOADDIR;
    
    /**
     * 解析失败存放目录
     */
    public static final String RESOLVE_ERROR_DIR;
    
    /**
     * 下载线程阻塞文件数
     */
    public static final int DOWNLOAD_WAIT_NUM;
    
    /**
     * 解析线程阻塞文件数
     */
    public static final int RESOLVE_WAIT_NUM;
    
    /**
     * 初始化相关配置  
     */
    static
    {
        Properties props = DBUtil.getProps();
        USERNAME = props.getProperty("username");
        PASSWORD = props.getProperty("password");
        HOSTNAME = props.getProperty("hostname");
        PORT = NumberUtils.toInt(props.getProperty("port"), 21);
        REMOTEDIR = props.getProperty("remotedir");
        DOWNLOADDIR = props.getProperty("downloaddir");
        RESOLVE_ERROR_DIR = props.getProperty("errordir");
        DOWNLOAD_WAIT_NUM = NumberUtils.toInt(props.getProperty("downloadnum"), 10);
        RESOLVE_WAIT_NUM = NumberUtils.toInt(props.getProperty("resolvenum"), 0);
    }
}

----------------------------------------------------

队列类:

public final class LockQueue
{
    private static final int MAX_LENGTH = 10;
    
    private static LockQueue instance = new LockQueue();
    
    private List<Object> list = new LinkedList<Object>();
    
    private Lock lock = new ReentrantLock();
    
    private Condition full = lock.newCondition();
    
    private Condition empty = lock.newCondition();
    
    private LockQueue()
    {
    }
    
    public static LockQueue getInstance()
    {
        return instance;
    }
    
    /**
     * 从队列取数据
     * <功能详细描述>
     * @return
     * @see [类、类#方法、类#成员]
     */
    public Object getObject()
    {
        Object t = null;
        lock.lock();
        try
        {
            while (0 == list.size())
            {
                empty.await();
            }
            t = list.remove(0);
            full.signal();
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        finally
        {
            lock.unlock();
        }
        return t;
    }
    
    /**
     * 放数据到队列中
     * <功能详细描述>
     * @param t
     * @see [类、类#方法、类#成员]
     */
    public void putObject(Object t)
    {
        lock.lock();
        try
        {
            while (MAX_LENGTH == list.size())
            {
                full.await();
            }
            list.add(t);
            empty.signal();
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        finally
        {
            lock.unlock();
        }
    }
}

----------------------------------------------

下载线程

public class RemoteLoadThread extends Thread
{
    /**
     * 下载队列
     */
    private LockQueue lockQueue;
    
    /**
     * 线程名
     */
    private String threadName;
    
    /**
     * ftp
     */
    private FTPClient ftpClient;
    
    /**
     * 输出流
     */
    private OutputStream os;
    
    /**
     * 需要下载文件队列
     */
    private Queue<String> remoteFiles = new Queue<String>();
    
    public RemoteLoadThread(LockQueue lockQueue)
    {
        super();
        this.lockQueue = lockQueue;
        this.threadName = "load ";
        remoteFiles.initialize();
        if (GeneralUtils.isNull(ftpClient))
        {
            this.ftpClient = new FTPClient();
        }
    }
    
    public RemoteLoadThread(LockQueue lockQueue, String threadName)
    {
        this.lockQueue = lockQueue;
        this.threadName = threadName;
        remoteFiles.initialize();
        if (GeneralUtils.isNull(ftpClient))
        {
            this.ftpClient = new FTPClient();
        }
    }
    
    /**
     * 获取所有远程解析文件名
     * <功能详细描述>
     * @return Queue<String>
     * @see [类、类#方法、类#成员]
     */
    private Queue<String> getRemoteFiles()
    {
        if (0 == remoteFiles.size())
        {
            if (getConn())
            {
                try
                {
                    FTPFile[] file = ftpClient.listFiles(InitData.REMOTEDIR);
                    for (int i = 0; i < file.length; i++)
                    {
                        remoteFiles.putMsg(file[i].getName());
                    }
                }
                catch (IOException e)
                {
                    LogUtils.runError(e.getMessage());
                }
            }
        }
        return remoteFiles;
    }
    
    /**
     * 获得ftp连接
     * <功能详细描述>
     * @return boolean
     * @see [类、类#方法、类#成员]
     */
    private boolean getConn()
    {
        boolean result = true;
        //登录用户名 密码
        try
        {
            //判断链接ftp服务器是否成功
            if (!ftpClient.isConnected())
            {
                ftpClient.connect(InitData.HOSTNAME, InitData.PORT);
            }
            ftpClient.login(InitData.USERNAME, InitData.PASSWORD);
            //检测连接是否成功
            int reply = ftpClient.getReplyCode();
            
            //显示连接失败
            if (!FTPReply.isPositiveCompletion(reply))
            {
                ftpClient.disconnect();
                LogUtils.runError("FTP server refused connection");
                result = false;
            }
        }
        catch (IOException e)
        {
            LogUtils.runError(e.getMessage());
        }
        ftpClient.setControlEncoding(GeneralConstant.CHARACTER_CODING);
        FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT);
        conf.setServerLanguageCode("zh");
        return result;
    }
    
    /**
     * 下载文件至指定的位置
     * 下载文件至系统默认的本地文件夹中
     * @param 提供时间戳功能
     * @return String
     * @see [类、类#方法、类#成员]
     */
    private String downloadFile(String name)
    {
        //时间戳
        String time = GeneralUtils.getCurrentTimeStamp();
        //本地文件名
        String localFileName = name.replace(".txt", time + ".txt");
        //本地文件路径
        String localFilePath = InitData.DOWNLOADDIR + localFileName;
        //远程文件路径
        String remoteFilePath = InitData.REMOTEDIR + name;
        //本地文件
        File localFile = new File(localFilePath);
        try
        {
            os = new FileOutputStream(localFile);
            //下载远程文件
            ftpClient
                .retrieveFile(new String(remoteFilePath.getBytes(GeneralConstant.CHARACTER_GBK), "ISO-8859-1"), os);
        }
        catch (FileNotFoundException e)
        {
            LogUtils.runError(e.getMessage());
        }
        catch (UnsupportedEncodingException e)
        {
            LogUtils.runError(e.getMessage());
        }
        catch (IOException e)
        {
            LogUtils.runError(e.getMessage());
        }
        return localFileName;
    }
    
    /**
     * 删除远程文件功能
     * 删除ftp上制定文件夹下的SIM卡信息文件,防止重复导入
     * @param remoteDir ftp的路径
     * @return boolean
     * @see [类、类#方法、类#成员]
     */
    private boolean removeFile(String remoteDir)
    {
        boolean flag = true;
        try
        {
            FTPFile[] files = ftpClient.listFiles(remoteDir);
            // 删除指定文件夹下所有文件
            for (FTPFile f : files)
            {
                String path = remoteDir + GeneralConstant.SEPARATOR + f.getName();
                if (f.isFile())
                {
                    ftpClient.deleteFile(path);
                }
            }
        }
        catch (IOException e)
        {
            e.getMessage();
            flag = false;
        }
        return flag;
    }
    
    /**
     * 下载ftp文件
     * <功能详细描述>
     * @see [类、类#方法、类#成员]
     */
    public void download()
    {
        //获取要下载的文件缓存
        getRemoteFiles();
        if (remoteFiles.size() > 0)
        {
            //远程有文件
            try
            {
                //获取并移除信息,如果队列为空,则阻塞等待
                String fileName = remoteFiles.getMsg();
                //下载
                fileName = downloadFile(fileName);
                //下载好的文件名放进队列
                lockQueue.putObject(fileName);
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
            finally
            {
                try
                {
                    if (0 == remoteFiles.size())
                    {
                        //需要下载的文件都下载完了
                        //删除远程文件
                        removeFile(InitData.REMOTEDIR);
                        ftpClient.logout();
                        ftpClient.disconnect();
                        //释放资源
                        closeSource();
                    }
                }
                catch (IOException ioe)
                {
                    LogUtils.runError(ioe.getMessage());
                }
            }
            
            LogUtils.runInfo("total :>" + remoteFiles.size());
        }
        else
        {
            LogUtils.runInfo("远程木有文件");
        }
    }
    
    /**
     * 释放资源
     * <功能详细描述>
     * @see [类、类#方法、类#成员]
     */
    private void closeSource()
    {
        if (GeneralUtils.isNotNull(os))
        {
            //释放资源
            try
            {
                os.close();
                LogUtils.runInfo("OutputStream close!");
            }
            catch (IOException e)
            {
                LogUtils.runError(e.getMessage());
            }
        }
    }
    
    @Override
    public void run()
    {
        while (true)
        {
            download();
            LogUtils.runDebug(threadName + "downLoad is runing...");
        }
    } 
}

---------------------------------------------------

public class AnalyzeThread extends Thread
{
    /**
     * 下载队列
     */
    private LockQueue lockQueue;
    
    /**
     * 线程名
     */
    private String threadName;
    
    /**
     * 解析Ok 缓存队列
     */
    private Queue<String> resQueue = new Queue<String>();
    
    public AnalyzeThread(LockQueue lockQueue)
    {
        super();
        this.lockQueue = lockQueue;
        resQueue.initialize();
    }
    
    public AnalyzeThread(LockQueue lockQueue, String threadName)
    {
        super();
        this.lockQueue = lockQueue;
        this.threadName = threadName;
        resQueue.initialize();
    }
    
    /**
     * 解析
     * <功能详细描述>
     * @see [类、类#方法、类#成员]
     */
    public void resolve()
    {
        try
        {
            //获取并移除信息,如果队列为空,则阻塞等待
            String fileName = (String)lockQueue.getObject();
            String path = GeneralUtils.filePathConcat(InitData.DOWNLOADDIR, fileName);
            File resFile = new File(path);
            //解析文件
            boolean result = FileUtil.readFile(resFile);
            if (result)
            {
                //将文件名放进解析成功队列
                resQueue.putMsg(fileName);
            }
            else
            {
                //将文件名放进解析失败目录里
                FileUtils
                    .copyFile(resFile, new File(GeneralUtils.filePathConcat(InitData.RESOLVE_ERROR_DIR, fileName)));
                resFile.delete();
            }
        }
        catch (IOException e)
        {
            LogUtils.runError(e.getMessage());
        }       
        LogUtils.runInfo("resolve :>" + resQueue.size());
    }
    
    @Override
    public void run()
    {
        while (true)
        {
            resolve();
            LogUtils.runDebug(threadName + "resolve is runing...");
        }
    }   
}

-----------------------------------------

test

public class TestMyThread
{
    public static void main(String[] args)
    {
        LockQueue lockQueue = LockQueue.getInstance();
        RemoteLoadThread reload = new RemoteLoadThread(lockQueue);
        AnalyzeThread analyze = new AnalyzeThread(lockQueue);       
        reload.start();
        analyze.start();
    }
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值