我编写了一个程序来计算文本中的行,单词和字符:它用线程来完成.它有时很好用,但其他时候却不那么好.最终发生的是指向单词数量的变量,计算的字符有时会变短,有时则不会.
在我看来,线程有时会在他们可以计算他们想要的所有单词或字符之前结束.是因为当while(true)循环中断时这些线程超出了范围吗?
我已经在下面的问题中包含了代码:
private void countText() { try { reader = new BufferedReader(new FileReader("this.txt")); while (true) { final String line = reader.readLine(); if(line == null) {break;} lines++; new Thread(new Runnable() {public void run() {chars += characterCounter(line);}}).start(); new Thread(new Runnable() {public void run() {words += wordCounter(line);}}).start(); println(line); } } catch(IOException ex) {return;} }
(子问题:这是我第一次询问某些内容并发布代码.我不想使用StackOverflow代替谷歌和维基百科,我担心这不是一个合适的问题?我试图让问题更一般,所以我不只是要求我的代码帮助......但是,是否有另一个网站,这种问题可能更合适?)
不同的线程设计可以更容易地找到并解决这类问题,并且更便于讨价还价.这是一个很长的响应,但总结是"如果你在Java中执行线程,请尽快检查java.util.concurrent "".
我猜你是多线程这个代码来学习线程而不是加速计算单词,但这是一种非常低效的使用线程的方法.你每行创建两个线程- 一千个线文件的两千个线程.创建线程(在现代JVM中)使用操作系统资源,并且通常相当昂贵.当两个 - 更不用说两千个线程 - 必须访问共享资源(例如你的chars
和words
计数器)时,由此产生的内存争用也会损害性能.
使计数器变量synchronized
作为克里斯金普顿暗示或Atomic
为WMR暗示将可能修复的代码,但它也将使竞争的效果差很多.我很确定它会比单线程算法慢.
我建议只有一个长期存在的线程,它会照看chars
,并且words
每个线程都有一个工作队列,每次要添加新号码时都会向其提交作业.这种方式只有一个线程写入每个变量,如果你对设计进行了更改,那么谁更明显谁负责什么.它也会更快,因为没有内存争用,你不会在紧密的循环中创建数百个线程.
一旦读完文件中的所有行,同样重要的是在实际打印出计数器的值之前等待所有线程完成,否则你将丢失尚未完成的线程的更新.使用您当前的设计,您必须建立一个您创建的大量线程,并在最后检查它们是否全部死亡.使用队列和工作线程设计,您可以告诉每个线程耗尽其队列,然后等待它完成.
Java(1.5及以上版本)使这种设计非常容易实现:查看java.util.concurrent.Executors.newSingleThreadExecutor.它还可以让以后更容易添加更多的并发性(假设正确的锁定等),因为您只需切换到线程池而不是单个线程.