简体   繁体   English

java.util.concurrent多线程

[英]java.util.concurrent multi-threading

I recently started messing with the java.util.concurrent, and I would like if someone could point out flaws or bad habits in my code. 我最近开始弄乱java.util.concurrent,希望有人指出我的代码有缺陷或不良习惯。

The program runs until a time out is reached, then outputs all the tasks that completed. 程序将运行直到达到超时,然后输出所有已完成的任务。

  • Should I be using ArrayList in this case? 在这种情况下,我应该使用ArrayList吗?
  • Is there a better suited class for this task that is perhaps more thread safe. 是否有更适合该任务的类,也许是线程安全的。
  • Any constructive criticism would help. 任何建设性的批评都会有所帮助。

Main Class 主班

public class ConcurrentPackageTests {

private final ExecutorService executor;

    public ConcurrentPackageTests() {
    executor = Executors.newFixedThreadPool(2);
    this.testCallable(4);
}

private void testCallable(int nInstances) {

    long startTime = System.currentTimeMillis();

    List<Future<Integer>>      futures = null;
    List<Integer>              results = null;
    ArrayList<exCallable>      callables = new ArrayList<exCallable>(nInstances);

    for (int id = 0; id < nInstances; id++) {callables.add(id, new exCallable(id,5));}  

    //get a list of the futures, monitor the futures outcome.
    try { futures = executor.invokeAll(callables, 5, TimeUnit.SECONDS);}
    catch (Exception e) { System.out.println("TIMED OUT");}

    executor.shutdown();    //Stop accepting tasks.

    System.out.println();

    results = getFValues(futures);  //gets all completed tasks
    printOutValues(results, startTime);

}

/**
 * get all integer values that terminated successfully.
 * @param e
 * @return Integer List of results
 */
private List<Integer> getFValues(List<Future<Integer>> e){
    final ArrayList<Integer> list = new ArrayList<Integer>(e.size());
    for (Future<Integer> f : e) {
        if(!f.isCancelled()){
            try {  list.add(f.get(1, TimeUnit.SECONDS));}
            catch (Exception e1) { System.out.println("Err");}      
        }
    }
    list.trimToSize();
    return list;
}

private void printOutValues(List<Integer> results, long startTime){
    for (Integer integer : results) {
        System.out.println("Result: " + integer);
    }   System.out.println("Time: "+ ( System.currentTimeMillis() - startTime ));
}

Callable 可召回

public class exCallable implements Callable<Integer>{

private int n;
int result = 1;
final int ID;

public int getResult() {
    return result;
}

public exCallable(int ID, int pN) {
    this.ID = ID;
    this.n = new Random().nextInt(pN)+ 1;
}

@Override
public Integer call() throws Exception{

    for (int i = 0; i < n; i++) {
        result *= 2;
        Thread.sleep(500);  //Simulate work.
    }

    System.out.println("Computation<" + ID + ">2^"+n+"="+result);
    return result;
}

}
  • Should I be using ArrayList in this case? 在这种情况下,我应该使用ArrayList吗?

All the executor does with this collection is iterate through it and add them to its own queue. 执行程序对此集合所做的所有工作都将对其进行迭代,并将它们添加到其自己的队列中。 Therefore almost any collection should do (should you have thousands of tasks and use a collection that is very costly to iterate, then maybe it could be a problem but that's a very rare situation!). 因此,几乎任何集合都应该执行此操作(如果您有成千上万的任务,并且使用的集合迭代成本很高,那么也许这可能是一个问题,但这是非常罕见的情况!)。

  • Is there a better suited class for this task that is perhaps more thread safe. 是否有更适合该任务的类,也许是线程安全的。

I think your choice of class/method is fine. 我认为您选择的课程/方法很好。 Can't think of a better suited class. 想不到一个更合适的班级。 There aren't really classes that are "more thread safe". 确实没有“线程安全性更高”的类。 Stuff are either thread safe or not. 东西是否是线程安全的。 At most there are classes that make coding thread safe programs easier. 最多有些类使编写线程安全程序更容易。 In this case I think you are going with a suitable level of abstraction. 在这种情况下,我认为您正在使用适当的抽象级别。

  • Any constructive criticism would help. 任何建设性的批评都会有所帮助。

(1) You should avoid member fields like the pest, and use local variables if at all possible. (1)您应避免使用像害虫这样的成员字段,并尽可能使用局部变量。 In this case, you can make result a local variable, so you should. 在这种情况下,可以将result设为局部变量,因此应该这样做。 When you have to use member fields, you should strive very hard to make them immutable. 当必须使用成员字段时,您应该尽力使它们不变。 In this case, both ID and n can be immutable by making them both final fields. 在这种情况下,通过将IDn都设置为最终字段,它们可以是不可变的。

(2) Creating a new Random object per task is a good decision IMO. (2)为每个任务创建一个新的Random对象是IMO的明智决定。 If you feel like it, you can use this common optimization: 如果您愿意,可以使用以下常见优化:

ThreadLocal<Random> rng = new ThreadLocal<Random>(){
    @Override
    protected Random init(){
        return new Random();
    }
}; 
// afterwards...
Random r = rng.get();

In case of Random you may not gain a lot, but this optimization can be highly effective when expensive objects (eg a JAXB parser) are involved. Random情况下,您可能不会收获很多,但是当涉及昂贵的对象(例如JAXB解析器)时,此优化可能非常有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM