public class Test {
private static final ExecutorService pool = Executors.newFixedThreadPool(10);
public static void main(String[] args) {
Test test = new Test();
test.processData("data/test.txt");
}
public void processData(String filePath){
File folder = new File(filePath);
for (String filename : folder.list()) {
String filePath = folder.toPath().resolve(filename).toString();
File inputfile = new File(filePath);
if (inputfile.isDirectory()) {
processData(filePath);
}else{
pool.execute(() -> {
log.info("Start processing " + filePath);
Processor.process(filePath);
});
}
}
}
class Processor{
private static final Logger log = LoggerFactory.getLogger(Processor.class);
public static void process(String filePath){
try{
List<Document> documets = DocumentProcessor.analyze(filePath);
...
}catch(IOException e){
e.printStackTrace();
}
}
}
class DocumentProcessor{
private static Tokenizer tokenizer = null;
private static Resource resource = null;
private static Checker checker = null;
private static final ExecutorService pool = Executors.newFixedThreadPool(4);
static {
// static initialization here
// ommited
}
public static List<Document> analyze(String filePath){
BufferedReader br = null;
List<Document> processedDocs = new ArrayList<>();
try {
br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath)));
String line = null;
List<Future<Document>> tasks = new ArrayList<>();
while ((line = br.readLine()) != null) {
line = line.trim();
Callable<Document> callable = new FileThread(line, filePath);
tasks.add(pool.submit(callable));
}
for (Future<Document> task : tasks) {
try {
processedDocs.add(task.get());
} catch (InterruptedException e) {
log.error("InterruptedException Failure: " + line);
} catch (ExecutionException e) {
log.error("Thread ExecutionException e: " + line);
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null)
br.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
return processedDocs;
}
}
public class FileThread implements Callable<Document> {
private String textLine;
private String filePath;
public TextThread(String textLine, String filePath) {
this.textLine = textLine;
this.filePath = filePath;
}
public Document call() {
ParsedDoc parsedDoc = JSONDocParser.parse(textLine, Source.news);
Document doc = new Document(parsedDoc.getURL(), parsedDoc.getDocTime());
doc.setDocument(Parser.parseDoc(parsedDoc.getText());
return doc;
}
}
在此代码中,多线程在processData()方法中与ExecutorService类一起使用。我的问题是: 1)在Processor或DocumentProcessor类中是否需要任何类型的线程同步?除了日志变量之外,类'Processor'没有任何实例或类变量。
2)如果这是一个大项目的一部分,并且唯一的多线程代码在Test类中,如此处所示。我是否需要担心所有其他类中的线程问题,假设所有其他类中都没有线程保护。
我问这个的原因是,根据我看到的例子,似乎在这个习惯用法中使用了ExecutorService,我不需要担心所有其他类中的线程问题,即处理器或DocumentProcessor。这是真的吗?
编辑: 请参阅我编辑的代码。我想现在它可以更好地说明我的问题。感谢。
答案 0 :(得分:2)
仅当一个关键部分由多个线程访问时才需要同步。在您的情况下,您似乎将其作为服务调用,并且在任何其他线程之间没有共享代码。
答案 1 :(得分:0)
您需要做的是使用同步保护代码的关键部分。这意味着仅,其中您的状态可能同时被多个线程修改。如果您无法访问DocumentProcessor代码,那么您可以围绕对analyze()的调用进行同步,但这可能过于粗糙。如果你的大部分工作都采用那种方法,那么你将失去使用多线程的大部分好处。
理想情况下,analyze()方法应该是线程安全的,因此只有在方法修改DocumentProcessor的静态实例变量的情况下才会进行同步。