我实施了一个在线商店,客户可以在其中下订单,我的程序会生成一个摘要,说明客户是谁以及他们购买了哪些商品。
public class Summarizer{
private TreeSet<Order> allOrders = new TreeSet<Order>(new OrderComparator());
public void oneThreadProcessing(){
Thread t1;
for(Order order: allOrders){
t1 = new Thread(order);
t1.start();
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void multipleThreadProcessing(){
Thread[] threads = new Thread[allOrders.size()];
int i = 0;
for(Order order: allOrders){
threads[i] = new Thread(order);
threads[i].start();
i++;
}
for(Thread t: threads){
try {
t.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main (String[] args) {
Summarizer s = new Summarizer();
long startTime = System.currentTimeMillis();
s.oneThreadProcessing();
long endTime = System.currentTimeMillis();
System.out.println("Processing time (msec): " + (endTime - startTime));
System.out.println("-------------Multiple Thread-------------------------------");
long startTime1 = System.currentTimeMillis();
s.multipleThreadProcessing();
long endTime1 = System.currentTimeMillis();
System.out.println("Processing time (msec): " + (endTime1 - startTime1));
这是我的订单类:
public class Order implements Runnable, Comparable<Order> {
private int clientId;
@Override
public void run() {
/*
Print out summary in the form:
Client id: 1001
Item: Shoes, Quantity: 2, Cost per item: $30.00, Total Cost: $60.00
Item: Bag, Quantity: 1, Cost per item: $15.00, Total Cost: $15.00
Total: $75.00
/*
}
}
假设我用特定日期的所有订单填写此TreeSet,并按客户ID号排序,我想使用一个线程然后多个线程生成所有这些订单的摘要并比较性能。要求是让多线程性能更好,我会假设它只是每次运行我的main方法。多线程实际上几乎总是较慢。难道我做错了什么?我知道人们永远无法确定多线程程序会更快但是由于我还没有处理任何锁定,我的程序在multipThreadedProcessing()中应该更快吗?有没有办法确保它更快?
答案 0 :(得分:5)
多线程并不是一种神奇的粉末,它可以洒在代码上以使其运行得更快。它需要仔细考虑你正在做什么。
让我们分析您编写的多线程代码。
你有很多Orders
(多少btw?几十?几百?千?百万?)并且在执行时,每个订单都会将自己打印到屏幕上。这意味着您正在产生可能数量庞大的线程,因此每个线程都会花费大部分时间等待System.out
变为可用(因为它将被其他线程占用)。每个线程都需要操作系统和JVM,还需要CPU时间和内存资源;那么为什么这样的多线程方法比单个线程运行得更快呢?单个线程不需要额外的内存,也不需要额外的上下文切换,也不必等待System.out
。所以自然会更快。
要使多线程版本更快地运行,您需要考虑一种在线程之间分配工作的方法,而不会对资源产生不必要的争用。首先,您可能不需要多个线程执行写入屏幕的 I / O 任务。写入System.out
的多个线程只会相互阻塞。如果您需要写入多个IO设备,则为每个设备创建一个或多个线程(取决于设备的性质)。 计算任务有时可以更快地并行执行,但是:
A)您不需要更多线程进行计算工作而不是CPU拥有的核心数。如果你有太多的CPU绑定线程,他们只是浪费时间上下文切换。
B)您需要通过并行处理进行推理,并进行彻底规划。给每个线程一个需要完成的计算任务的块,然后组合每个线程的结果。