可以创建多个线程共享的for循环吗?

时间:2015-11-10 14:23:06

标签: java multithreading

我正在尝试创建一个程序,它将为每个线程提供一个整数,然后线程将使用该整数计算给定代码,然后返回以获取另一个整数。这将继续,直到计算出所有需要计算的整数。

由于我对多线程没有多少经验,我不知道如果完成第一项任务,我怎么能拿出一个线程并改变它的工作。

目前,这是我创建和执行线程的方式:

public static void main(String[] args){
    ComputableInteger a = new ComputableInteger(1);
    ComputableInteger b = new ComputableInteger(2);
    ComputableInteger c = new ComputableInteger(3);
    Thread t1 = new Thread(a);
    Thread t2 = new Thread(b);
    Thread t3 = new Thread(c);
    t1.start();
    t2.start();
    t3.start();
}

现在,这工作正常,但它只计算3个已经决定的整数。我希望能够选择他们必须计算多少个整数,并且线程应该始终只占用该行中的第一个空闲数字。因此,例如,我不想只将前10个整数分配给t1,将下一个整数分配给t2,依此类推。相反,我希望第一个线程完成,获取行中的下一个整数(在这种情况下为4)。

我一直在关注threadPools,但我也无法做到这一点。我希望你们中的一些人有一些提示!

修改

好的,所以我尝试使用synchronized实现getNext,这就是我的run函数的样子:

public void run() {
    while (Executer.getNext() < 20) {
        if(computeInteger(number)) {
            Executer.incrementCount();
        }
        number = Executer.getNext();
    }
}

希望它能检查每个单个整数,最多19个。这样做,但它设法在途中跳过几个数字,并且看到我已经同步了,我不完全确定我是如何解决这个问题的。

修改

我切换到ExecuterService来解决这个问题,但是我对如何正确执行它有一些问题:

public static void main(String[] args){
    final long startTime = System.currentTimeMillis();
    executorService.execute(new Runnable() {
        public void run() {
            int currentNumber;
            while ((currentNumber = Executer.getNext()) <= 10000000) {
                if(Executer.computeInteger(currentNumber)) {
                    Executer.incrementCount();
                }
            }
        }
    });

从我所看到的当前问题是,第一个线程是执行所有代码的线程。但是,如果我想将其分成一个线程进行1次迭代,而所有其他线程同步运行,我该怎么做呢?

3 个答案:

答案 0 :(得分:4)

使用ExecutorService类创建固定大小的线程池。将计算逻辑放入可运行的类中。迭代for循环中的所有整数值,并在每次迭代时通过传递要执行计算的数据创建可运行对象,并将其提交给ExecutorService线程池。

答案 1 :(得分:1)

创建一个只能通过同步的getter访问的静态字段。

private static int next = 1;

public static synchronized int getNext() {
    return next++;
}

在线程中,每次需要新号码时都会调用此方法!

编辑: getNext()方法已经递增了计数器,因此您只需要调用一次:

public void run() {
    while ((number = Executer.getNext()) < 20) {
        // Do whatever you have to do with number
        // but don't increment the next counter anymore
    }
}

答案 2 :(得分:1)

如果你不想使用Executor服务,你也可以使用java 8新流api:

public static void main(String[] args) {

    List<Integer> integerToTreat = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);

    long start = System.currentTimeMillis();
    integerToTreat.parallelStream().forEach(i -> {
        // do your work here. For this example, just sleeping 1sec.
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    });
    System.out.println("Finished treating " + integerToTreat.size() + " items in " + (System.currentTimeMillis() - start) + " ms");
}

将输出:Finished treating 8 items in 2068 ms

有了这个,你就无法选择线程数或线程池。它使用的是使用此api的所有循环共享的固定的一个,其中包含与cpu中的核心一样多的线程。