2013-04-11 159 views
1

我有一个简单的工具,它坪一组节点,并返回一个字符串到未来的对象一个ArrayList将被输出到文件中。程序应该运行直到用户终止。Java线程:期货只用结果从第一和最后一个线程

它不会出现未来接收结果(或至少将它们传递给该方法,以输出到文件)。不管我同时运行的线程数量(总是小于100,由输入文件决定),我只输出第一个和最后一个初始化线程的结果。

作为一个全面的检查,我创建了一个全局变量,其中每个线程将关闭并返回其结果对未来对象之前发送其结果。这个变量被所有线程正确更新。

没有人有任何想法,为什么未来似乎没有被接收我从线程所有结果?

public class PingUtility{ 
    public static ExecutorService pool = Executors.newFixedThreadPool(100); 
    static Future<ArrayList<String>> future; 

    public static void main(String[] args) throws Exception { 

     Timer timer = new Timer(); 
     TimerTask task = new TimerTask(){ 
      public void run(){ 
       //Creates a pool of threads to be executed 
       ArrayList<String[]> nodes = new ArrayList<String[]>() 
       future = pool.submit(new PingNode(nodes)); 
       } 
      } 
     }; 

     timer.scheduleAtFixedRate(task, 0, interval); 

     while(true){ 
      try{ 
       ArrayList<String[]> tempOutputArray = future.get(); 
       Iterator<String[]> it = tempOutputArray.iterator(); 
       while(it.hasNext()) appendFile(it.next()); 
       tempOutputArray.clear(); 
      }catch(Exception nullException){ 
      //Do nothing 
      } 
     } 
    } 
+0

只是为了后人,你应该总是记录异常(特别是NPE)。如果迭代器可以得到一个'null',那么你应该在代码中处理它。 – Gray 2013-04-11 14:33:24

回答

3

你的问题是,你正在修改的future静态字段,而无需在定时任务线程(S)同步,并在主线程读取它。您需要在修改时对其进行同步,或者使用其他机制在线程之间共享信息。

我建议从static字段切换到LinkedBlockingQueue作为一种更好的方式发送信息从PingNode调用appendFile(...)方法。这节省了从需要自己做同步,并防止在比赛条件,其中多个定时器任务将开始,消费者可以从get()他们之前覆盖future。可能是这样的:

BlockingQueue<String[]> queue = new LinkedBlockingQueue<String[]>(); 
... 

// inside of run, producer passes the queue into the PingNode 
public void run() { 
    pool.submit(new PingNode(queue)); 
} 

// consumer 
while (true) { 
    String[] array = queue.take(); 
    ... 
} 

这不会影响您完成后如何停止线程。如果定时器任务被终止,实体可以向队列添加一个终止对象来停止主循环。

+0

谢谢,我将不得不考虑如何正确实施它。 – Yabo9797 2013-04-11 14:08:19

+0

我的意思是排队字符串[]。那么在你的例子中,我根本不会使用未来?队列被用于存储PingNode的结果吗?如果是这样,我想我需要修改方法来同时处理输入和队列来处理输出? – Yabo9797 2013-04-11 14:23:08

+0

是的,不需要使用'未来'。我考虑推荐一个'BlockingQueue ',但似乎没有必要。你将一个'List'传递给'PingNode',所以直接传入'queue'是有道理的。 – Gray 2013-04-11 14:30:09

0

Future对象是不是一个仓,像一个ArrayList,它仅仅指向一个单一的计算结果。因为你只有一个指向这个Future的静态指针,我想象的是这样的:

future = null 
    nullException 
    nullException 
    nullException 
    nullException 
    ... 
    First thread finally sets future = Future<ArrayList<String>> 
    Call to future.get() blocks... 
     Meanwhile, all other threads get scheduled, and they reassign future 
     The last thread will obviously get the last say in what future points to 
    Data is gathered, written to file, loop continues 
    future now points to the Future from the last thread 
    Results from last thread get printed 
+0

谢谢,这听起来像是怎么回事。你会推荐LinkedBlockingQueue吗?有没有办法通过将它们放入类似对象的容器中来处理结果,我只需要抓住第一个结果,然后处理它,然后转到下一个结果? – Yabo9797 2013-04-11 14:07:59

+0

这就是LinkedBlockingQueue的功能。线程put()到队列阻塞,直到另一个线程poll()从它那里获得,同样,poll()的线程将挂起,直到另一个线程放入()为止。 – torquestomp 2013-04-11 14:22:26

相关问题