1

我有一个简单的实用程序,它 ping 一组节点并将字符串的 ArrayList 返回到将来的对象以输出到文件。该程序应该一直运行到用户终止。

未来似乎没有收到结果(或至少将它们传递给方法以输出到文件)。无论我同时运行的线程数(总是小于 100,由输入文件确定),我只输出第一个和最后一个初始化线程的结果。

作为健全性检查,我创建了一个全局变量,每个线程将在其中发送其结果,然后关闭并将其结果返回给 Future 对象。此变量由所有线程正确更新。

有谁知道为什么 Future 似乎没有从线程中收到我所有的结果?

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
            }
        }
    }
4

2 回答 2

3

您的问题是您正在修改future静态字段而没有在定时器任务线程中同步并在主线程中读取它。您需要在修改读取它时对其进行同步,或者使用另一种机制在线程之间共享信息。

我建议从一个static字段切换到LinkedBlockingQueue一个更好的方式来将信息从PingNode调用发送到appendFile(...)方法。这样可以避免需要自己进行同步,并防止多个计时器任务将启动并覆盖future消费者之前的竞争条件get()。也许是这样的:

 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();
     ...
 }

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

于 2013-04-11T13:57:08.333 回答
0

Future 对象不像 ArrayList 那样是 bin,它只是指向单个计算结果。因为你只有一个指向这个 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
于 2013-04-11T14:02:43.603 回答