同时启动多个线程

时间:2017-01-06 03:02:33

标签: java multithreading

对于我们的类分配,我们必须通过将它分成n个段来计算txt文件中的单词数量,我们应该能够在启动程序之前设置它们。然后每个段应该获得自己的线程,该线程对单词进行计数然后停止。最后,主线程应该收集所有单个字数并将它们加在一起。

这是我到目前为止写的(部分)

for (int i = 0; i < segments; i++){
            Thread thread = new Thread();
            thread.start();
            int words = counting(stringarray[i]);
            totalwords += words;
            long nanos = ManagementFactory.getThreadMXBean().getThreadCpuTime(Thread.currentThread().getId());
            System.out.println("This Thread read " + words + " words. The total word count now is " + totalwords + 
                    ". The time it took to finish for this thread is " + nanos +".");
            System.out.println("Number of active threads from the given thread: " + Thread.activeCount());
        }

现在,虽然这可以完成主要工作(计算不同线程中的单词并将它们添加到总计中),但我不知道如何“保留线程”,然后在每个线程之后将各个单词计数添加到一起完成了它的工作。

此外,虽然这肯定会启动多个线程,但它只打印出我有2个,或者一次运行3个线程,即使我将txt拆分为100个段。有没有办法让它们同时运行?

3 个答案:

答案 0 :(得分:1)

问题的措辞表明每个线程都有自己的计数器,所以我会声明一个线程类:

public class WordCounter extends Thread {
    private String text;
    private int count;

    public WordCounter(String text) {
        this.text = text;
    }

    public int getCount() {
        return count;
    }

    @Override
    public void run() {
        count = counting(text);
    }
}

并按如下方式使用:

WordCounter[] threads = new WordCounter[segments];
for (int i = 0; i < segments; ++i) {
    threads[i] = new WordCounter(stringarray[i]);
    threads[i].start();
}
int total = 0;
for (int i = 0; i < segments; ++i) {
    threads[i].join();
    total += threads[i].getCount();
}

答案 1 :(得分:0)

您可以使用下一个代码段作为基础。 请注意,如果您在不同的线程中增加公共变量,则此操作必须是线程安全的。这就是AtomicInteger变量用作计数器

的原因
final List<String> segments = new ArrayList<>();
//TODO:Fill segments ... this is up to you
//In case threads will increment same variable it has to be thread-safe
final AtomicInteger worldCount = new AtomicInteger();
//Create Thread for each segment (this is definitely not optimal)
List<Thread> workers = new ArrayList<>(segments.size());
for (int i = 0; i < segments.size(); i++) {
    final String segment = segments.get(i);
    Thread worker = new Thread(new Runnable() {
        @Override
        public void run() {
            //increment worldCount
            worldCount.addAndGet(counting(segment));
        }
    });
    workers.add(worker);
    worker.start();
}

//Wait until all Threads are finished
for (Thread worker : workers) {
    worker.join();
}
int result = worldCount.get();

答案 2 :(得分:0)

相同的解决方案,但使用Executors:

    final List<String> segments = new ArrayList<>();
    segments.add("seg1");
    segments.add("seg2");
    segments.add("seg 3");

    final AtomicInteger worldCount = new AtomicInteger();

    List<Future> workers = new ArrayList<>(segments.size());
    ExecutorService executor = Executors.newFixedThreadPool(segments.size());
    for (String segment : segments) {
        Future<Integer> worker = executor.submit(() -> worldCount.addAndGet(counting(segment)));
        workers.add(worker);
    }

    executor.shutdown();
    if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
        System.out.println("Still waiting...");
        System.exit(0);
    }

    int result = worldCount.get();

    System.out.println("result = " + result);