抽象和封装与性能不一致 - 如何?

时间:2015-03-19 16:51:47

标签: java multithreading concurrency thread-safety

我一直在阅读这本书," Java Concurrency in Practice",其中,在Tread Safety章节中,提到: "有时抽象和封装与性能不一致"。 我没有得到这一部分。有人可以用一个例子解释一下吗?

提前致谢。

2 个答案:

答案 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;