简体   繁体   English

让所有线程等待方法完成

[英]Make all threads wait for a method to finish

I have currently two threads running in a main. 我目前有两个线程在一个主线程中运行。 In one of the threads I have a method that writes data to a file (.txt) (thread 1) and in the other thread I have method that reads data from the same file (thread 2). 在一个线程中,我有一种将数据写入文件(.txt)(线程1)的方法,在另一个线程中,我有一种从同一文件中读取数据的方法(线程2)。 I wonder is there a way to when the read method in thread 2 is executing make the other thread wait with its execution until the read method in thread 2 finishes? 我想知道有什么方法可以使线程2中的read方法执行时,使另一个线程等待其执行,直到线程2中的read方法完成?

This is how it looks: Thread 1: 外观如下:线程1:

Function that writes data to a file want to wait here until Thread 2 read method finishes 将数据写入文件的函数要在这里等待,直到线程2读取方法完成
writeTextToFile(text) writeTextToFile(文本)

Thread 2: 线程2:

method to read data from a file same file as thread 2 writes to execute in peace without any other thread running until it finishes readFile(); 从与线程2写入相同文件的文件中读取数据的方法,可以在不运行任何其他线程的情况下和平执行,直到完成readFile()为止;

code below: 下面的代码:

package parser;

import java.util.ArrayList;
import java.util.List;
import java.io.StringReader;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import utils.ReadMachine;
import utils.TextProcessor;
import utils.WriteMachine;
import edu.stanford.nlp.process.Tokenizer;
import edu.stanford.nlp.process.TokenizerFactory;
import edu.stanford.nlp.process.CoreLabelTokenFactory;
import edu.stanford.nlp.process.PTBTokenizer;
import edu.stanford.nlp.ling.CoreLabel;
import edu.stanford.nlp.trees.*;
import edu.stanford.nlp.parser.lexparser.LexicalizedParser;

public class Parser implements Runnable {

    private String parserModel;
    private LexicalizedParser lp;
    private ReadMachine rwm;
    private WriteMachine wm;
    private TextProcessor tp;
    private String from;
    private int nbr;
    private static final Logger logger = LoggerFactory.getLogger(Parser.class);

    public Parser(String from, String to, int nbr) {
        rwm = new ReadMachine();
        this.nbr = nbr;
        this.from = from;
        this.parserModel = "edu/stanford/nlp/models/lexparser/englishPCFG.ser.gz";

        this.tp = new TextProcessor();
        this.wm = new WriteMachine(to);
    }

    public String parser(String toBeParsed) {

        Tree parse;

        if (toBeParsed == null) {
            toBeParsed = "This is a sentence.";
        }

        TokenizerFactory<CoreLabel> tokenizerFactory = PTBTokenizer.factory(
                new CoreLabelTokenFactory(), "");
        Tokenizer<CoreLabel> tok = tokenizerFactory
                .getTokenizer(new StringReader(toBeParsed));
        List<CoreLabel> raw = tok.tokenize();

        parse = lp.apply(raw);

        TreebankLanguagePack tlp = lp.treebankLanguagePack(); // PennTreebankLanguagePack
                                                                // for English
        GrammaticalStructureFactory gsf = tlp.grammaticalStructureFactory();
        GrammaticalStructure gs = gsf.newGrammaticalStructure(parse);
        List<TypedDependency> tdl = gs.typedDependenciesCCprocessed();

        return tdl.toString();

    }

    private void parseFromTo() {
        ArrayList<String> proc = null;
        proc = rwm.readFile(from);
        if (proc != null && proc.size() > 0) {
            proc = tp.sentenceDivider(proc);
        }
        for (String line : proc) {
            logger.info(line);
        }
    }

    @Override
    public void run() {


        while (true) {
                WANT this method to execute in peace
                this.parseFromTo();
            try {
                Thread.sleep(3 * 1000);
            } catch (InterruptedException e) {
                logger.info("Sleep interupted");
            }
        }
    }

}

package crawler;

import java.io.OutputStream;
import java.util.Set;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import edu.uci.ics.crawler4j.crawler.Page;
import edu.uci.ics.crawler4j.crawler.WebCrawler;
import edu.uci.ics.crawler4j.parser.HtmlParseData;
import edu.uci.ics.crawler4j.url.WebURL;

public class Crawler extends WebCrawler {
    private static final Logger logger = LoggerFactory.getLogger(Crawler.class);
    public static String newline = System.getProperty("line.separator");
    @SuppressWarnings("unused")

    private int index;
    private static int indx = 0;

    private final static Pattern FILTERS = Pattern
            .compile(".*(\\.(css|js|bmp|gif|jpe?g"
                    + "|png|tiff?|mid|mp2|mp3|mp4"
                    + "|wav|avi|mov|mpeg|ram|m4v|pdf"
                    + "|rm|smil|wmv|swf|wma|zip|rar|gz|txt))$");
    private String[] patterns = { "[Mm][Ii][Gg]", "[Mm][Aa][Gg]",
            "[Gg][Mm][Aa][Ww]", "[Ww][Ee][Ll][Dd][Ii][Nn][Gg]" };

    private String path = "/Users/aloefqvi/Dropbox/1337_Haxor/LTH/courses/EDAN70/parse_files/from/text/"
            + "from" + Integer.toString(this.index = indx++) + ".txt";

    private Downloader dl = new Downloader(patterns, path);

    protected void setOs(OutputStream os) {

    }

    /**
     * You should implement this function to specify whether the given url
     * should be crawled or not (based on your crawling logic).
     */
    public boolean shouldVisit(WebURL url) {
        String href = url.getURL().toLowerCase();
        return !FILTERS.matcher(href).matches();
    }


    @Override
    public void visit(Page page) {

        if (page.getParseData() instanceof HtmlParseData) {
            HtmlParseData htmlParseData = (HtmlParseData) page.getParseData();
            String text = htmlParseData.getText();
            Set<WebURL> links = htmlParseData.getOutgoingUrls();
            String urlData = "";
            for (WebURL item : links) {
                urlData = urlData + newline + item;
            }
                WANT this thread to wait here until parseToFile finishes
                dl.download(text.trim(), false);

        }

    }



}

I suppose file locking do it for you. 我想文件锁定可以为您完成。
But, to communicate between threads in a process, better methods exist. 但是,为了在进程中的线程之间进行通信,存在更好的方法。 See Queues 请参阅队列

One way of doing this is to use a Lock (specifically, usually a ReentrantLock). 一种方法是使用 (通常是ReentrantLock)。 Essentially, you create a Lock object to administer access to the file. 本质上,您将创建一个Lock对象来管理对该文件的访问。 Then, before performing a read or write on the file, you call lock() -- which waits if the lock (and hence the file) is already in use by the other thread. 然后,在对文件执行读取或写入之前,调用lock()-等待该锁(以及文件)是否已被其他线程使用。 Once a given thread is done reading/writing, it calls unlock() to free up the lock, which another waiting thread will then immediately acquire as applicable. 一旦给定线程完成读/写操作,它将调用unlock()释放锁,然后另一个等待线程将根据需要立即获取该锁。

If appropriate for your application, you also have the option of a ReentrantReadWriteLock, which potentially allows multiple reads at the same time. 如果适合您的应用程序,您还可以选择ReentrantReadWriteLock,它可能允许同时进行多次读取。

A bit of synchronization will solve your issue but it will be great if you can change your approach and switch to latest java concurrency utilities ,from java 1.5 we have BlockingQueue available . 一点同步将解决您的问题,但是如果您可以更改方法并切换到最新的Java并发实用程序,那就太好了,从Java 1.5开始,我们提供了BlockingQueue。 eg -> 例如->

Use the method take and offer and leave everything else to queue. 使用方法take and offer并让其他所有内容排队。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM