Java 多线程比单线程更快

Java 多线程比单线程更快,java,multithreading,performance,Java,Multithreading,Performance,我正在实施一个在线商店,顾客在那里下订单,我的程序生成客户是谁以及他们购买了什么商品的摘要 public class Summarizer{ private TreeSet<Order> allOrders = new TreeSet<Order>(new OrderComparator()); public void oneThreadProcessing(){ Thread t1; for(Order order: allOrders){

我正在实施一个在线商店,顾客在那里下订单,我的程序生成客户是谁以及他们购买了什么商品的摘要

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));
公共类摘要器{
private TreeSet allOrders=new TreeSet(new OrderComparator());
public-void-oneThreadProcessing(){
螺纹t1;
对于(订单:allOrders){
t1=新螺纹(订单);
t1.start();
试一试{
t1.join();
}捕捉(中断异常e){
e、 printStackTrace();
}
}
}
public void multipleThreadProcessing(){
线程[]线程=新线程[allOrders.size()];
int i=0;
对于(订单:allOrders){
线程[i]=新线程(顺序);
线程[i].start();
i++;
}
用于(螺纹t:螺纹){
试一试{
t、 join();
}捕捉(中断异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}           
}
}
公共静态void main(字符串[]args){
摘要器s=新摘要器();
long startTime=System.currentTimeMillis();
s、 一线程处理();
long-endTime=System.currentTimeMillis();
System.out.println(“处理时间(毫秒):”+(endTime-startTime));
System.out.println(“--------------多线程--------------------”;
long startTime1=System.currentTimeMillis();
s、 多线程处理();
long-endTime1=System.currentTimeMillis();
System.out.println(“处理时间(毫秒):”+(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
        /*

    }
}
公共类顺序实现可运行、可比较的{
私人int客户ID;
@凌驾
公开募捐{
/*
以以下格式打印摘要:
客户编号:1001
项目:鞋,数量:2,每项成本:$30.00,总成本:$60.00
项目:袋子,数量:1,每项成本:$15.00,总成本:$15.00
总额:75.00美元
/*
}
}

假设我在这个树集中填写了某一天的所有订单,这些订单是按客户ID编号排序的,我想只使用一个线程,然后使用多个线程生成所有这些订单的摘要,并比较性能。要求是多线程性能更好,我会假设每个线程都会更好ime我运行我的main方法。多线程实际上几乎总是比较慢。我做错了什么吗?我知道人们永远无法确定多线程程序会更快,但既然我还没有处理任何锁定,我的程序在多线程处理()中不应该更快吗?有什么方法可以确保它运行得更快吗?

多线程并不是一种神奇的粉末,它需要你仔细考虑你在做什么

让我们分析一下您编写的多线程代码

您有许多
订单
(顺便问一下,有多少?几十?数百?数千?百万?),执行时,每个订单都会自动打印到屏幕上。这意味着您可能会产生大量线程,因此每个线程都会花费大部分时间等待
System.out
可用(因为它将被其他线程占用)。每个线程都需要操作系统和JVM的参与,再加上它需要CPU时间和内存资源;那么为什么这样的多线程方法要比单个线程运行得更快呢?单个线程不需要额外的内存,也不需要额外的上下文切换,也不需要等待
System.out
。因此自然会更快

为了让多线程版本更快地工作,您需要考虑一种在线程之间分配工作的方法,而不会对资源产生不必要的争用。例如,您可能不需要多个线程来执行写入屏幕的I/O任务。多个线程写入
System.out
w您只需互相阻塞。如果您有多个IO设备需要写入,则为每个设备创建一个或多个线程(取决于设备的性质)。计算任务有时可以更快地并行执行,但:

A)执行计算工作所需的线程数不必超过CPU的核心数。如果CPU线程太多,它们只会浪费时间切换上下文


B)您需要通过并行处理进行推理,并对其进行全面规划。为每个线程分配一块需要完成的计算任务,然后将每个任务的结果合并起来。

关于如何加快处理速度的建议?不要使用System.out,而只需将打印的字符串分配给例如,一个名为String summary的实例变量。然后使用getter访问每个订单的摘要?@samz_manu我对答案进行了一点扩展,看看这是否有帮助。是的,这将消除对System.out不必要的争用,但仍然(可能)会为许多线程创建一条路径。