我最近开始使用java.util.concurrent,我希望有人能指出我的代码中的缺陷或坏习惯。
程序运行到超时,然后输出所有已完成的任务。
主班
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 ));
}可赎回
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;
}
}发布于 2012-08-19 11:00:37
执行器对该集合所做的所有操作都是遍历它,并将它们添加到自己的队列中。因此,几乎所有的集合都应该这样做(如果您有数千个任务,并且使用一个非常昂贵的迭代集合,那么它可能是一个问题,但这是一个非常罕见的情况!)
我认为你选择班级/方法是可以的。想不出更合适的课程了。没有真正的类是“更安全的线程”。东西要么是线程安全的,要么不是。最多有一些类可以使编写线程安全程序变得更容易。在这种情况下,我认为您需要一个适当的抽象级别。
(1)您应该避免像pest这样的成员字段,并尽可能使用局部变量。在这种情况下,您可以使result成为一个局部变量,所以您应该这样做。当您必须使用成员字段时,您应该非常努力地使它们成为不变的。在这种情况下,ID和n都可以是不可变的,因为它们都是最终字段。
(2)为每个任务创建一个新的Random对象是一个很好的决策。如果您喜欢,可以使用以下常见优化:
ThreadLocal<Random> rng = new ThreadLocal<Random>(){
@Override
protected Random init(){
return new Random();
}
};
// afterwards...
Random r = rng.get();在Random的情况下,您可能不会获得很多,但是当涉及到昂贵的对象(例如JAXB解析器)时,这种优化可能会非常有效。
https://stackoverflow.com/questions/12024832
复制相似问题