我正在尝试创建一个程序,它将为每个线程提供一个整数,然后线程将使用该整数计算给定代码,然后返回以获取另一个整数。这将继续,直到计算出所有需要计算的整数。
由于我对多线程没有多少经验,我不知道如果完成第一项任务,我怎么能拿出一个线程并改变它的工作。
目前,这是我创建和执行线程的方式:
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次迭代,而所有其他线程同步运行,我该怎么做呢?
答案 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中的核心一样多的线程。