我一直在阅读这本书," Java Concurrency in Practice",其中,在Tread Safety章节中,提到: "有时抽象和封装与性能不一致"。 我没有得到这一部分。有人可以用一个例子解释一下吗?
提前致谢。
答案 0 :(得分:2)
长话短说:首先做对,然后改善表现。
有时你会跳过篮球试图提高性能,有时会导致错误或糟糕的设计。更不用说,这很费时间!严格按照性能进行编程将导致代码难以扩展,严格按照设计进行编程(可能)会导致更多开销。
我认为查看它的好方法是封装是一种限制形式;如何访问/修改某些内容的设置限制。这些限制可能会带来性能代价。
完整的引用声明:
有时抽象和封装与性能不一致 - 虽然不像许多开发人员所认为的那样频繁 - 但是首先要使代码正确,然后快速实现,这总是一个好习惯
答案 1 :(得分:1)
线程示例:
好的和慢的代码:
//Several classes doing each one its thing.
public class Task1 implements Runnable { ... }
public class Task2 implements Runnable { ... }
public class Task3 implements Runnable { ... }
//Collection with runnable instances
List<Runnable> tasks = new ArrayList<Runnable>();
//A producer would have populated the list with some instances depending on some conditions
if(cond1) tasks.add(new Task1());
if(cond2) tasks.add(new Task2());
if(cond3) tasks.add(new Task3());
//Now we execute tasks without caring what do they do.
ExecutorService executor = Executors.newFixedThreadPool(1);
for(Runnable r : tasks){
executor.execute(r);
}
现在糟糕而快速的代码:
new Thread(){
@Override
public void run(){
if(cond1){
//do task 1
} else if(cond2){
//do task 2
} else if(cond3){
//do task 3
}
}
}.start();
第一种情况是抽象方面最好的(因此从测试和维护的角度来看,这是专业软件开发中最重要的)。生产者和消费者是分离的,消费者执行者并不关心如何实施任务。但是必须实例化任务,这意味着缓慢。
通常,创建实例的速度很慢,因为管理堆需要CPU周期,因为需要跟踪和分配或释放内存。在Java中,垃圾收集器随机运行的另一个问题是,如果我们在内存上做空,可能需要分配额外的堆。
第二个减速来自函数调用(必须调用每个任务的函数run
来执行它的操作)。函数调用比根本不调用慢,因为必须跟踪堆栈和参数传递等。
第二个片段很乱,每个任务有效负载都混乱了。这是真正的编码恐怖。而且,它既产生又消耗任务。但是,由于没有创建任何实例,并且没有函数调用,因为每个任务的代码都是内联的,所以它会很快。
你可能没有在这段代码中看到我的观点,因为只有3个任务只运行一次,但想象一下,如果任务是以每秒一千的速度生成的。例如,这可能发生在处理请求的网络服务器中,或者由飞机仪表系统处理飞行仪表读数。
通常情况下,更干净的代码更慢。
正如Knuth所说,
&#34;过早优化是所有邪恶的根源&#34;