Java 在线程中读取解析消息的

Java 在线程中读取解析消息的,java,multithreading,parsing,Java,Multithreading,Parsing,如果标题有点模糊,请原谅。我将努力更好地解释我正在努力实现的目标 有一个名为parsebytes的函数,它是我实现的外部接口的一部分。它需要一个字节数组和一个长度。这个特定程序中的所有解析都在单个线程上运行,因此我希望尽快从parsebytes中获取数据,以便它可以返回到离线获取更多数据。我的伪代码方法如下: 创建一个外部运行的线程(ParserThreadClass)。 每次调用parsebytes时,通过循环所有字节并执行byteQueue.add(bytes[i]),将字节放入Parser

如果标题有点模糊,请原谅。我将努力更好地解释我正在努力实现的目标

有一个名为parsebytes的函数,它是我实现的外部接口的一部分。它需要一个字节数组和一个长度。这个特定程序中的所有解析都在单个线程上运行,因此我希望尽快从parsebytes中获取数据,以便它可以返回到离线获取更多数据。我的伪代码方法如下: 创建一个外部运行的线程(ParserThreadClass)。 每次调用parsebytes时,通过循环所有字节并执行byteQueue.add(bytes[i]),将字节放入ParserReadClass中的队列中。此代码由一个同步(字节队列)包围 实际上,这将释放parsebytes返回并获取更多数据

在这种情况下,我的ParserThreadClass也在运行。这是run()函数中的代码


我在这里效率太低了吗?如果是这样,有人能告诉我应该如何解决这个问题吗?

这是我以前试图解决这个问题的方法。基本上,您有一个生产者线程,就像这里一样,它读取文件并将项目放入队列。然后您有一个工作线程,它从队列中读取并处理这些内容。下面是代码,但它看起来与您正在做的基本相同。我发现这并没有给我任何加速,因为相对于磁盘读取,我每行需要做的处理速度非常快。如果您必须进行的解析非常密集,或者数据块非常大,那么您可以看到这样做的速度有所加快。但是,如果它是非常小的,不要期望在性能改进方面看到太多,因为这个过程是受IO限制的。在这些情况下,您需要并行化磁盘访问,这在一台机器上是无法实现的

public static LinkedBlockingQueue<Pair<String, String>> mappings;
public static final Pair<String, String> end =
    new Pair<String, String>("END", "END");
public static AtomicBoolean done;
public static NpToEntityMapping mapping;
public static Set<String> attested_nps;
public static Set<Entity> possible_entities;

public static class ProducerThread implements Runnable {
    private File f;

    public ProducerThread(File f) {
        this.f = f;
    }

    public void run() {
        try {
            BufferedReader reader = new BufferedReader(new FileReader(f));
            String line;
            while ((line = reader.readLine()) != null) {
                String entities = reader.readLine();
                String np = line.trim();
                mappings.put(new Pair<String, String>(np, entities));
            }
            reader.close();
            for (int i=0; i<num_threads; i++) {
                mappings.put(end);
            }
        } catch (InterruptedException e) {
            System.out.println("Producer thread interrupted");
        } catch (IOException e) {
            System.out.println("Producer thread threw IOException");
        }
    }
}

public static class WorkerThread implements Runnable {
    private Dictionary dict;
    private EntityFactory factory;

    public WorkerThread(Dictionary dict, EntityFactory factory) {
        this.dict = dict;
        this.factory = factory;
    }

    public void run() {
        try {
            while (!done.get()) {
                Pair<String, String> np_ent = mappings.take();
                if (np_ent == end) {
                    done.set(false);
                    continue;
                }
                String entities = np_ent.getRight();
                String np = np_ent.getLeft().toLowerCase();
                if (attested_nps == null || attested_nps.contains(np)) {
                    int np_index = dict.getIndex(np);
                    HashSet<Entity> entity_set = new HashSet<Entity>();
                    for (String entity : entities.split(", ")) {
                        Entity e = factory.createEntity(entity.trim());
                        if (possible_entities != null) {
                            possible_entities.add(e);
                        }
                        entity_set.add(e);
                    }
                    mapping.put(np_index, entity_set);
                }
            }
        } catch (InterruptedException e) {
            System.out.println("Worker thread interrupted");
        }
    }
}
公共静态LinkedBlockingQueue映射;
公共静态最终对端=
新的一对(“结束”、“结束”);
公共静态原子;
公共静态NpToEntityMapping映射;
公共静态集认证的\u nps;
公共静态设置可能的_实体;
公共静态类ProducerThread实现可运行{
私有文件f;
公共产品阅读(文件f){
这个。f=f;
}
公开募捐{
试一试{
BufferedReader reader=新的BufferedReader(新文件读取器(f));
弦线;
而((line=reader.readLine())!=null){
字符串实体=reader.readLine();
字符串np=line.trim();
put(新对(np,实体));
}
reader.close();

对于(int i=0;我想:如果没有要解析的内容,这段代码会做什么?您需要添加合理的
notify
/
wait
语义。parseMessage()函数在继续之前检查字节数是否大于4。我应该在.addAll(字节队列)中添加这种检查吗?如果字节数小于4,它会做什么?它必须继续做什么?如果它返回,此代码将再次调用它。它将如何停止?它只是返回。线程预计在TCP连接时正在运行。如果队列中没有任何内容,则可能会有下一次迭代。@mattg的答案是最简单的使用BlockingQueue的一个简单的功能示例。但是,请注意,对于您关于效率的“更大问题”的答案是,您应该分析应用程序,看看哪个实现对您的性能最好。哪个解决方案是“正确的”一个取决于您的实际程序特征,您只能通过实际的运行时评测来了解这一点。我的一些消息最多可达7200字节,因此它们是大量的。通常情况下,这不是真的,但是parseMessage()函数有一个状态机,所以我正在逐字节读取/构建。请注意,
LinkedBlockingQueue
执行上面David Schwartz所说的
notify/wait
。我想您可能在parseMessage()中使用了类似的内容方法,这就是为什么我说这基本上等同于您正在做的事情。如果您不这样做,您可能希望使用
LinkedBlockingQueue
。如果您需要帮助编写启动并加入这些生产者线程和工作者线程的方法,我也可以向您展示如何做到这一点。我是LBQ的新手。我会详细阅读并回来如果我需要帮助,谢谢。我很快就能实现我认为正确的LBQ代码。你能给我看一下开始/加入代码吗?还有-制作人(如果我这么称呼它的话),在您的示例中不是真正的生产者。从线路上读取字节的函数充当生产者,我将原子布尔值和LBQ变量放入该类中。侦听器位于另一个类中,并按照您的定义静态引用变量。听起来合理吗?我编辑了原始帖子,我想我回答了您的问题纳什。
public static LinkedBlockingQueue<Pair<String, String>> mappings;
public static final Pair<String, String> end =
    new Pair<String, String>("END", "END");
public static AtomicBoolean done;
public static NpToEntityMapping mapping;
public static Set<String> attested_nps;
public static Set<Entity> possible_entities;

public static class ProducerThread implements Runnable {
    private File f;

    public ProducerThread(File f) {
        this.f = f;
    }

    public void run() {
        try {
            BufferedReader reader = new BufferedReader(new FileReader(f));
            String line;
            while ((line = reader.readLine()) != null) {
                String entities = reader.readLine();
                String np = line.trim();
                mappings.put(new Pair<String, String>(np, entities));
            }
            reader.close();
            for (int i=0; i<num_threads; i++) {
                mappings.put(end);
            }
        } catch (InterruptedException e) {
            System.out.println("Producer thread interrupted");
        } catch (IOException e) {
            System.out.println("Producer thread threw IOException");
        }
    }
}

public static class WorkerThread implements Runnable {
    private Dictionary dict;
    private EntityFactory factory;

    public WorkerThread(Dictionary dict, EntityFactory factory) {
        this.dict = dict;
        this.factory = factory;
    }

    public void run() {
        try {
            while (!done.get()) {
                Pair<String, String> np_ent = mappings.take();
                if (np_ent == end) {
                    done.set(false);
                    continue;
                }
                String entities = np_ent.getRight();
                String np = np_ent.getLeft().toLowerCase();
                if (attested_nps == null || attested_nps.contains(np)) {
                    int np_index = dict.getIndex(np);
                    HashSet<Entity> entity_set = new HashSet<Entity>();
                    for (String entity : entities.split(", ")) {
                        Entity e = factory.createEntity(entity.trim());
                        if (possible_entities != null) {
                            possible_entities.add(e);
                        }
                        entity_set.add(e);
                    }
                    mapping.put(np_index, entity_set);
                }
            }
        } catch (InterruptedException e) {
            System.out.println("Worker thread interrupted");
        }
    }
}
    Thread producer = new Thread(new ProducerThread(f), "Producer");
    producer.start();
    ArrayList<Thread> workers = new ArrayList<Thread>();
    for (int i=0; i<num_threads; i++) {
        workers.add(new Thread(new WorkerThread(dict, factory), "Worker"));
    }
    for (Thread t : workers) {
        t.start();
    }
    try {
        producer.join();
        for (Thread t : workers) {
            t.join();
        }
    } catch (InterruptedException e) {
        System.out.println("Main thread interrupted...");
    }