是Java I / O绑定(或)CPU绑定中的多线程

时间:2015-04-04 04:33:59

标签: java multithreading

我已经开始学习多核编程和开发并行算法。这可以通过在Java中使用多线程来轻松完成。因此,我创建了两个包含10行内容的文本文件,如下所示:

This is the first line in file 1
This is the second line in file 1
This is the third line in file 1 
This is the fourth line in file 1
This is the fifth line in file 1
This is the sixth line in file 1
This is the seventh line in file 1
This is the eighth line in file 1
This is the ninth line in file 1
This is the tenth line in file 1

同样,在其他文本文件中,文件1 将替换为文件2 。我编写了一个程序来读取文件的内容,包括和不包含线程。它们如下:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;

public class SimpleThread {

    static void printFile(BufferedReader br) throws Exception
    {
        for(String line; (line = br.readLine())!=null; )
            System.out.println(line);
    }

    public static void main(String args[]) throws Exception
    {
        double startTime = System.nanoTime();
        BufferedReader br1 = new BufferedReader(new FileReader(new File("test1.txt")));
        BufferedReader br2 = new BufferedReader(new FileReader(new File("test2.txt")));
        SimpleThread.printFile(br1);
        SimpleThread.printFile(br2);
        System.out.println(System.nanoTime() - startTime + "ns");
    }
}

使用多线程的程序如下:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;

public class Threading extends Thread{

    BufferedReader br;

    public Threading(String fileName)
    {
        try{
        br = new BufferedReader(new FileReader(new File(fileName)));
        start();
        }
        catch(Exception e)
        {
            System.out.println(e.getMessage());
        }
    }

    private void printFile(BufferedReader br) throws Exception
    {
        for(String line; (line = br.readLine())!=null; )
            System.out.println(line);
    }

    public void run()
    {
        try{
        printFile(br);
        }
        catch(Exception e)
        {
            System.out.println(e.getMessage());
        }
    }

    public static void main(String args[]) throws Exception
    {
        double startTime = System.nanoTime();
        Threading t1 = new Threading("test1.txt");
        Threading t2 = new Threading("test2.txt");
        System.out.println(System.nanoTime() - startTime + "ns");
    }
}

现在,当我比较两个程序的执行时间时,我发现单线程程序需要 1544589.0ns ,而多线程程序需要 410522.0ns

我很想知道速度增加的因素。我发现它大约是 0.23

在修改使用多个线程的代码之后,我发现单个线程程序执行得更快,这更大程度上增加了我的困惑。

以下是修订后的代码:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;

public class Threading extends Thread{

    BufferedReader br;

    public Threading(String fileName)
    {
        try{
        br = new BufferedReader(new FileReader(new File(fileName)));
        start();
        }
        catch(Exception e)
        {
            System.out.println(e.getMessage());
        }
    }

    private void printFile(BufferedReader br) throws Exception
    {
        for(String line; (line = br.readLine())!=null; )
            System.out.println(line);
    }

    public void run()
    {
        try{
        printFile(br);
        }
        catch(Exception e)
        {
            System.out.println(e.getMessage());
        }
    }

    public static void main(String args[]) throws Exception
    {
        double startTime = System.nanoTime();
        Threading t1 = new Threading("test1.txt");
        Threading t2 = new Threading("test2.txt");
        t1.join(); //waiting for t1 to finish
        t2.join(); //waiting for t2 to finish
        System.out.println(System.nanoTime() - startTime + "ns");
    }
}

现在执行时间是: 单螺纹 - 1459052.0ns
多线程 - 1768651.0ns

为什么系统会以不自然的方式运行?

现在,我的问题是:

  1. 会增加线程数,减少执行时间吗?
  2. 何时应该使用多线程编写程序
  3. 可以将相同的文件概念移植到数据库,其中每个线程根据类别读取数据库的一部分,说明有关新闻,体育,政治等的信息将由相应的线程读取,最后结果将被打成一团。这可行吗?
  4. mutlithreading应该只用于CPU绑定程序吗?

2 个答案:

答案 0 :(得分:2)

  

我很想知道速度增加的因素。我发现它大约是0.23。

这是因为您的多线程测试无效。它实际上并不测量线程所用的时间。相反,它只是测量启动线程的时间。

其他测试也无效。您没有考虑JVM预热效果......并且测试所做的工作量不足以作为指示。

另一个问题是,读取文件所花费的时间(例如在Linux上)取决于操作系统是否已经缓存它。因此,如果您运行其中一个测试然后再次运行它,您很可能会发现它第二次显着更快!

  

现在执行时间是:Single Threaded - 1459052.0ns   多线程 - 1768651.0ns

     

为什么系统会以不自然的方式运行?

这实际上是我期望发生的......对于该版本的基准测试。由于使用两个线程进行读取,创建两个线程的开销似乎超过任何(假设的)加速。


您的问题:

  

Q1。会增加线程数,减少执行时间吗?

它可能会。这取决于您拥有多少个内核,线程是CPU还是I / O限制,是否存在数据结构或资源争用等等。

  

Q2。何时应该在编写程序时使用多线程

当考虑性能时,问题可以合理地划分为可以并行执行的子任务。此外,对于小问题,设置线程的开销可能会超过任何可能的性能提升。

  

Q3。是否可以将相同的文件概念移植到数据库中,其中每个线程根据类别读取数据库的一部分,如新闻,体育,政治等信息将由相应的线程读取,最后结果将被聚集在一起。这可行吗?

也许。

但是,您的(无效)测试可能会让您误解多线程的好处。实际上,任何涉及读取或写入光盘的内容都受到光盘驱动器具有单个读/写"头部"它一次只能进行一次硬件级读写操作。操作系统或数据库系统可以通过各种技巧来提供更快性能的印象,但如果应用程序足够强大,那么就会碰壁。

简而言之,理论上可能只有有限的加速量。

  

Q4。多线程是否应仅用于CPU绑定程序?

没有。

但这并不意味着多线程应该用于所有事情。

它甚至不应该用于所有CPU绑定程序!

简单的概括不适用。它更复杂。

答案 1 :(得分:0)

线程是一个协助并行执行的概念。很多时候我们看到CPU处于空闲状态,其处理速度远远超过人工或者小代码片段。当我们引入线程时,我们会尝试通过确保它有足够的指令集来执行来减少CPU的空闲时间。

让我们举个例子;

在每笔交易中,我们确实有一些预先& amp;在我们实际进入核心业务逻辑(由CPU执行)之前发布要遵循的基本步骤。在这些活动期间,CPU处于空闲状态。通过多线程,我们确保在实际处理一个线程的同时,另一个线程的前/后活动也同时执行,因此一旦第一个线程的处理结束,就可以采取第二个任务进行处理。

回到下一个问题,我们应该为基本功能而不是核心业务逻辑实现多线程,因为它可能会产生负面影响。

如果可能,我们总是尝试为昂贵的活动引入并行执行(这需要更多时间)。