首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >多线程--更快的方法?

多线程--更快的方法?
EN

Stack Overflow用户
提问于 2014-06-18 06:59:10
回答 6查看 128关注 0票数 0

我在某个字段上有一个带有getter getInt()和setter setInt()的类,比如说字段。

代码语言:javascript
复制
Integer Int; 

类的对象,比如SomeClass

这里的setInt()是同步的-- getInt()不是。

我正在多个线程中更新Int的值。每个线程都得到值Int,并适当地设置它。线程没有以任何方式共享任何其他资源。

每个线程中执行的代码如下所示。

代码语言:javascript
复制
public void update(SomeClass c) {

        while (<condition-1>) // the conditions here and the calculation of 
                                   // k below dont have anything to do 
                                   // with the members of c
            if (<condition-2>) {
                // calculate k here 
                synchronized (c) {                        
                        c.setInt(c.getInt()+k); 
                    //    System.out.println("in "+this.toString());
                }
            }  
}   

run()方法只是通过传递给它的params在构造函数内部更新的成员上调用上面的方法:

代码语言:javascript
复制
public void run() { update(c); } 

当我在大的序列上运行这个线程时,线程并没有太多地交织--我看到一个线程在执行很长时间,而没有在中间运行任何其他线程。

一定有更好的方法来做这件事。

我不能更改SomeClass或调用线程的类的内部结构。

如何才能做得更好?

蒂娅。

//=。

编辑:

我不是在操纵线程的执行顺序。他们都有同样的优先权。只是我在结果中看到的是,线程没有平均地分配执行时间--其中之一,一旦接管,执行。但是,我不明白为什么这段代码会这样做。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2014-06-18 07:19:08

只是我在结果中看到的是线程没有平均分配执行时间

如果你追求效率,这正是你不想要的。从执行中拉出一个线程,并调度另一个线程通常是非常昂贵的。因此,做one of them, once takes over, executing on实际上是有利的。当然,当这是过度时,您可以看到更高的吞吐量,但更长的响应时间。理论上是这样。在实践中,JVM线程调度几乎可以用于所有目的,并且您不希望尝试在几乎所有情况下更改它。根据经验,如果您对毫秒级的响应时间感兴趣,那么您可能希望远离干扰它。

博士:这不是低效的,你可能想保持原样。

编辑:

尽管如此,使用AtomicInteger可能有助于性能,在我看来,比使用锁(synchronized关键字)更容易出错。但是,为了获得可测量的好处,您需要非常努力地打击该变量。

票数 1
EN

Stack Overflow用户

发布于 2014-06-18 07:11:28

JDK为多线程int access (AtomicInteger)提供了一个很好的解决方案:

http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicInteger.html

票数 1
EN

Stack Overflow用户

发布于 2014-06-18 09:00:45

作为Enno Shioji has pointed out,让一个线程继续执行可能是在某些情况下执行代码的最有效方法。

这取决于线程同步对代码的其他工作(我们不知道)造成了多少成本。如果您有一个循环,如:

代码语言:javascript
复制
while (<condition-1>)
    if (<condition-2>) {
        // calculate k here 
        synchronized (c) {                        
            c.setInt(c.getInt()+k); 
        }
    }

与同步成本相比,条件-1和条件-2的测试和k的计算相当便宜,Hotspot优化器可能会决定通过将代码转换为如下所示来减少开销:

代码语言:javascript
复制
synchronized (c) {                        
    while (<condition-1>)
        if (<condition-2>) {
            // calculate k here 
            c.setInt(c.getInt()+k); 
        }
}

(或者一个更复杂的结构,通过执行循环展开和跨synchronized块进行多次迭代)。底线是,优化后的代码可能会阻塞其他线程更长的时间,但让拥有锁的线程完成得更快,从而导致整体执行速度更快。

这并不意味着单线程执行是处理问题的最快方法。这也并不意味着在这里使用AtomicInteger是解决问题的最佳选择。它会产生更高的CPU负载,可能还会带来很小的加速,但它不能解决您的真正错误:

完全没有必要在循环中以高频率更新c。毕竟,您的线程并不依赖于及时看到对c的更新。甚至看起来他们根本没有使用它。因此,正确的解决方法是将更新移出循环:

代码语言:javascript
复制
int kTotal=0;
while (<condition-1>)
    if (<condition-2>) {
        // calculate k here
        kTotal += k;
    }
synchronized (c) {                        
    c.setInt(c.getInt()+kTotal); 
}

现在,所有线程都可以并行运行(假设这里没有发布的代码不包含线程间依赖项),并且synchronization成本降低到最小。您仍然可以将其更改为AtomicInteger,但这不再那么重要了。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24278938

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档