Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java中的线程处理技术_Java_Multithreading - Fatal编程技术网

java中的线程处理技术

java中的线程处理技术,java,multithreading,Java,Multithreading,这是我的第一个专业线程应用程序,对我来说有些困惑 我需要从API获取大量数据,在API中,我向三个不同的API端点提供一个id,根据返回非空值的端点,我必须解析和处理数据 我有一个工作版本的这个,但没有使用线程,这是需要太长的时间来完成 其主要思想是,我正在使用一个ID池,并试图在一个循环内连接到API。每个循环都在创建一个处理连接和数据解析的新对象 public void connect(){ For(String id:idList){ String url="...."

这是我的第一个专业线程应用程序,对我来说有些困惑

我需要从API获取大量数据,在API中,我向三个不同的API端点提供一个id,根据返回非空值的端点,我必须解析和处理数据

我有一个工作版本的这个,但没有使用线程,这是需要太长的时间来完成

其主要思想是,我正在使用一个ID池,并试图在一个循环内连接到API。每个循环都在创建一个处理连接和数据解析的新对象

public void connect(){
    For(String id:idList){
      String url="...."+id;
      String reply=getData(url);
      if(reply!=null){
         //parse data
         parse(reply);
      } 
    }
}
public void parse(String data){
   //....
}
所以我想尝试一下线程,以防它加快速度。 到目前为止,我的尝试似乎是有效的,我可以连接并下载数据,但我还没有想出如何限制我创建的线程,以避免溢出或内存不足错误。 从我的研究中,我发现如果已经有太多线程在运行,我可以将新创建的线程置于睡眠状态,比如

但这是创建线程,只是暂停它,所以我认为它会消耗RAM,就好像它正在运行一样,并且考虑到我有好几千个ID,这肯定会给我带来问题。 因此,如果我可以阻止在主类中创建线程,这将更有意义。我怎么能这样做?如果我在上面的示例中使用计数器,我不知道每个线程何时终止以开始创建新线程。 另一方面,我看到了wait/notify方法,但我不确定如何实现它,因为我正在创建新对象,因此无法同时通知它们。 我试图阅读Oracle的Java教程,但这让我更加困惑

更新不是解决方案 我确实设法改变了我的类作为线程运行,使用了一个池,这对于任何有类似错误的人来说都是正确的选择,但是我遇到了连接问题,我使用的是jdbc mySql连接和安全副本/Jcraft连接,这是一个正确设置的问题。我在尝试连接时遇到了连接打开和/或关闭或打开的连接太多的异常。我猜这是因为当我编写应用程序时,我在方法内部打开和关闭这些连接,然后该方法转向线程,导致打开多个打开的连接。这是太多的truble现在改变,所以我只是要改变回到单线程的方法

也许这对我来说应该是一个教训,用面向线程的方法设计我的程序,如果需要的话,把它作为一个单线程使用

但这是在创建线程,只是暂停它

实际上,它只是在消耗CPU

所以我认为它会消耗RAM,就好像它正在运行一样

它消耗CPU而不是RAM

考虑到我有好几千个ID,这肯定会给我带来麻烦

一旦线程数超过内核数,就会出现问题,最有可能是4个左右

因此,如果我可以阻止在主类中创建线程,这将更有意义。我怎么能这样做

我会使用一个队列并传递它的工作,如果您想限制活动线程的数量,我也会使用一个线程池,比如一个固定大小的线程池

如果我在上面的示例中使用计数器,我不知道每个线程何时终止以开始创建新线程

你永远不会,因为你的计数器不是线程保存,而另一个线程可能永远也看不到它的更新

另一方面,我看到了wait/notify方法,但我不确定如何实现它,因为我正在创建新对象,因此无法同时通知它们

您可以向他们传递一个他们都可以查看的对象,但就像我说的,固定大小的线程池执行器要简单得多

我试图阅读Oracle关于并发性的Java教程,但这让我更加困惑

由于您希望处理所有数据并收集结果,我建议您使用并行流

public void connect(){
    List<String> results = idList.parallelStream()
                                 .map(id -> fetchDataAndParse(id))
                                 .collect(Collectors.toList());
}
我还没有想出如何限制我创建的线程

这强烈表明您需要一个固定大小的线程池。见上文Peter+1 Lawry的答案

我想试试线程,以防它加快速度

在任何程序中使用线程基本上有两个原因:

1在有多个CPU的机器上进行并行计算。当我说计算时,它可以是数学,或者几乎可以是你的程序所做的任何其他事情,在没有做太多IO的情况下使用大量CPU时间

2简化程序的结构,该程序对由不同、独立或部分独立的外部事件源驱动的不同抽象过程进行建模

在单线程事件驱动程序中,主事件循环必须接收并分类所有不同类型的事件,然后 调用驱动各种进程的处理程序。每个进程的状态必须在处理程序调用之间保持的数据结构中显式编码。理解这样一个项目中正在发生的事情可能是一个挑战


在多线程程序中,每个抽象进程都可以由自己的线程建模,进程的大部分状态可以由线程的程序计数器和调用堆栈隐式表示。多线程程序通常比等效的事件驱动程序更易于阅读。但是线程本身也有挑战性,编写正确的多线程程序本身也有挑战性。

我建议您使用ScheduledExecutorService。如果您真的必须直接使用线程,我建议不要对线程进行子类化,而是包装一个可运行的线程。我建议查看执行器和线程池。请参阅:@PeterLawrey除了直接使用线程,我还有什么选择?我使用的是Runnable,不是吗?@SkarosIlias我建议远离你从中获得该示例的网站。基于这段代码,它的质量非常低。@SkarosIlias我不知道你在向我们展示你没有编写的代码。首先,你的回答中有几个要点:1我认为thread.sleep不使用cpu!你确定吗?2创建对象并初始化变量时,是否为这些变量使用和保存ram?2没有考虑队列,会考虑它们,当然结合线程。3您能否提供您提到的等待/通知技术的示例?4我得看看parallelStream,我以前见过。Thanks@SkarosIliasThread.sleep1不使用CPU,但//睡眠忙碌等待。@SkarosIlias是的,但在RAM耗尽之前,您将耗尽CPU和允许的线程,您可以轻松拥有一百万个这样的对象。十年前,当Java 5.0问世时,wait/notify并不是最佳实践,如果您发现多线程令人困惑,我会认真避免它,即使这样。。。
public void connect(){
    For(String id:idList){
      String url="...."+id;
      ThreadClass thread= new ThreadClas(url);
      Thread t = new Thread(thread);
       t.start();
    }
}
class ThreadClass implements Runnable{
   public final int MAX_THREADS = 10;
   public int threads_counter = 0; 

   public void run() {
       while(this.threads_counter >= this.MAX_THREADS){
          //sleep
        }
       threads_counter++;
       //fetch data and parse
       threads_counter--;
   }
}
public void connect(){
    List<String> results = idList.parallelStream()
                                 .map(id -> fetchDataAndParse(id))
                                 .collect(Collectors.toList());
}