Java中的并行读写应用程序

时间:2013-10-17 06:55:23

标签: java multithreading queue

我正在java中开发一个应用程序,我正在使用共享的LinkedBlocking Queue,我正在创建多个线程来读取和写入它。我已经创建了如下代码,但我无法获得所需的结果。

结果我正在使用一个共享文件,这个文件由两个线程写入(读写一个)。

请告诉我代码中的错误:

Message Reader.java

package com.aohandling.messagereader;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import com.aohandling.messagequeue.MessageQueue;

public class MessageReader implements Runnable
{
    public static BufferedWriter out;

    public static void init()
    {
    file = new File("AOHandle.txt");
    try
    {
        out = new BufferedWriter(new FileWriter(file, true));
        System.out.println("Init ");
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
    }

    static File file = null;

    public void run()
    {
    while (true)
    {
        try
        {
        SimpleDateFormat ft = new SimpleDateFormat("E yyyy.MM.dd 'at' hh:mm:ss a zzz");
        String s = MessageQueue.getMessageQueue().poll();
        if (s != null)
        {
            out.write("queue - " + MessageQueue.getMessageQueue().poll() + "---"  + ft.format(new Date()) + "\n");
        }

        }
        catch (IOException e)
        {
        e.printStackTrace();
        }
    }
    }
}

MessageWriter.java

package com.aohandling.writer;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import com.aohandling.messagequeue.MessageQueue;
import com.aohandling.messagereader.MessageReader;

public class MessageWriter implements Runnable
{

    int n;
    private int messageSequence;

    public MessageWriter(int messageSequence)
    {
    this.messageSequence = messageSequence;
    }

    public void run()
    {

    try
    {
        SimpleDateFormat ft = new SimpleDateFormat("E yyyy.MM.dd 'at' hh:mm:ss a zzz");
        MessageReader.out.append("Writing----AO - " + this.messageSequence + "-----" + ft.format(new Date()) + "\n");
        MessageQueue.getMessageQueue().put("AO " + this.messageSequence);
    }
    catch (IOException | InterruptedException e)
    {
        e.printStackTrace();
    }
    }
}

MessageQueue.java

package com.aohandling.messagequeue;

import java.util.concurrent.LinkedBlockingQueue;

public class MessageQueue {

    private static LinkedBlockingQueue<String> messageQueue = new LinkedBlockingQueue<String>();

    public static LinkedBlockingQueue<String> getMessageQueue() {
        return MessageQueue.messageQueue;
    }

    public static void setMessageQueue(LinkedBlockingQueue<String> messageQueue) {
        MessageQueue.messageQueue = messageQueue;
    }
}

TestAOHandlingRead.java

package com.aohandling.main;

import com.aohandling.messagereader.MessageReader;
import com.aohandling.writer.MessageWriter;

public class TestAOHandlingRead
{

    /**
     * @param args
     */
    public static void main(String[] args)
    {
    MessageReader.init();
    for (int i = 0; i <= 200; i++)
    {
        Thread readThread = new Thread(new MessageReader());
        readThread.start();
    }
    write();

    }
    public static void write()
    {
    for (int i = 0; i <= 20; i++)
    {
        if (i % 2 == 0)
        {
        try
        {
            Thread.sleep(500);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        }

        Thread writeThread = new Thread(new MessageWriter(i));
        writeThread.start();

    }
    }
}

TestAOHandlingWrite.java

package com.aohandling.main;

import java.util.concurrent.atomic.AtomicInteger;

import com.aohandling.writer.MessageWriter;

public class TestAOHandlingWrite {

    int count = 0;

    public int getCount()
    {
        return count;
    }

    /**
     * @param args
     */
    public static void main(String[] args) {

//      MessageWriter.init();
        for (int i=0; i<= 20; i++) {
         if (i%2 ==0) {
             try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
         }

         Thread writeThread = new Thread(new MessageWriter(i));
            writeThread.start();

        }


    }

}

1 个答案:

答案 0 :(得分:0)

我建议您使用FileChannel,因为文件通道可以安全地供多个并发线程使用。另外,我重构了你的代码,在类加载器第一次加载MessageReader类的过程中,你的文件的通道将被创建一次。

public class MessageReader implements Runnable {
    private static FileChannel channel;

    static {
    try {
        System.out.println("Init ");
        FileOutputStream fileOutputStream = new FileOutputStream(
                "AOHandle.txt", true);

        FileChannel channel = fileOutputStream.getChannel();
        System.out.println("Init ");

    } catch (IOException e) {
        e.printStackTrace();
    }
    }

        public void run() {
    while (true) {
        FileLock fileLock = null;
        try {
            SimpleDateFormat ft = new SimpleDateFormat(
                    "E yyyy.MM.dd 'at' hh:mm:ss a zzz");
            String s = MessageQueue.getMessageQueue().poll();
            if (s != null) {
                String message = "queue - "
                        + MessageQueue.getMessageQueue().poll() + "---"
                        + ft.format(new Date()) + "\n";
                fileLock = channel.lock();
                channel.write(ByteBuffer.wrap(message.getBytes()));
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fileLock != null) {
                    fileLock.release();
                }
            } catch (IOException e) {

                e.printStackTrace();
            }
        }
    }
}
}

最佳做法是在一个位置打开一个文件的频道,并在你的线程之间共享,因为在你的代码中没有人关闭文件。