您的位置:首页 > 其它

多线程误区:一定会提高效率

2015-04-11 10:49 302 查看
最近在做项目的时候,遇到要对一批大量的数据进行加工处理,于是有人提出了这样一种实现方案:

同时开好几个线程,让这几个线程同时对这批数据进行处理,并认为这样可以提高CPU的利用率,从而提高程序的性能。

其实这样就是对多线程的一个误解,认为多线程一定可以提高系统的发性能,其实不能一概而论。

我们利用多线程做优化的目的是减少IO等待的时间,把一个【纯计算】任务分到多个线程并不会提高CPU的利用率,反而会增加线程间切换的开销。在单核、无IO操作、纯计算的情况下,单线程的执行效率是要比多线程高的,因为线程间来回切换也要一定的开销。但是一般很少系统是只有 计算,而没有IO操作的。所以性能优化的方向应该是对IO操作进行优化,而不是对计算操作进行优化。

Java提供的ArrayBlockingQueue阻塞队列是典型的 生产者 - 消费者 问题的数据结构,利用这个阻塞队列,可以实现读取数据和处理数据两个线程间的并行,减少CPU在IO操作的等待时间,从而提高程序的性能。

为了验证在【纯计算】环境下单线程与多线程的性能差异,我们设计如下测试用例:让一个线程不断对一个数字做减一操作,直到数值减为0,最后统计整个过程花费的时间。在相同的环境下,利用三个线程对这个数据做减一操作,直到数值减为0,计算整个过程花费的时间:

public class Demo1
{
public static void main(String[] args)
{
long startTime = System.currentTimeMillis();
new Test(startTime).start();
}
}

class Test
{
private long startTime;
public Test(long startTime)
{
this.startTime = startTime;
}

int num = 1000000;
Object look = new Object();

public void start()
{
Thread th1 = new Thread(new Runnable()
{
@Override
public void run()
{
calc();
}
}, "Thread1");

Thread th2 = new Thread(new Runnable()
{
@Override
public void run()
{
calc();
}
}, "Thread2");

Thread th3 = new Thread(new Runnable()
{
@Override
public void run()
{
calc();
}
}, "Thread3");

th1.start(); // 只有一个线程在计算
//th2.start();
//th3.start();
}

private void calc()
{
while (true)
{
synchronized (look)
{
if (num > 0)
{
num--;
System.out.println(Thread.currentThread().getName() + " = " + num);
}
else
{
System.out.println(System.currentTimeMillis() - startTime);
break;
}
}
}
}
}


下面分别是在【单线程】、【双线程】和【三线程】的情况下,3次测试的用时(毫秒):

单线程:13295、13233、13334  平均用时:13287.33333333333

双线程:13331、13292、13262  平均用时:13295

三线程:13372、13294、13384  平均用时:13350

分析测试数据不难发现,其实三种情况下差异并不大,因此我们可以得结论:

把一个【纯计算】任务分到多个线程同时执行并不会提高CPU的利用率,反而会增加线程间切换的开销。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  多线程 操作系统