2

我有一些代码在这里

 public void doScan() {
    Log.i(LOG_TAG, "Start scanning");

    ExecutorService executor = Executors.newFixedThreadPool(NB_THREADS);
    for(int dest=0; dest<255; dest++) {
        String host = "192.168.5." + dest; //add net address instead of hardcoding
        executor.execute(pingRunnable(host));
    }

    Log.i(LOG_TAG, "Waiting for executor to terminate...");
    executor.shutdown();
    try { executor.awaitTermination(10*1000, TimeUnit.MILLISECONDS); } catch (InterruptedException ignored) { }
    Log.i(LOG_TAG, "Scan finished");
}


private Runnable pingRunnable(final String host) {
    return new Runnable() {
        public void run() {
            Log.v(LOG_TAG, "Pinging " + host + "...");
            try {
                Socket s = null;
                s = new Socket(InetAddress.getByName(host), ACES_PORT);

                Log.v(LOG_TAG, "conn:"+s.toString());
                if(s.isConnected()){
                    Log.v(LOG_TAG, "connected " + host);
                    foundDevicesArray.add(host);
                }


            } catch (UnknownHostException e) {
                Log.e(LOG_TAG, "Not found", e);
            } catch (IOException e) {
                Log.e(LOG_TAG, "IO Error", e);
            }
        }
    };
}

如果主机在线程内连接,我正在尝试保存它。

我有一个全局的(我是 android 的新手,所以我不确定它是否是这样的)ArrayList,在我执行 ArrayList.add(host) 的线程内它崩溃了我不知道如何获取来自崩溃的常见错误消息。

4

1 回答 1

2

您需要按如下方式初始化变量以赋予其非空值:

static List<String> foundDevicesArray = new ArrayList<String> ();

但是请注意,arraylists 不是线程安全的,因此您应该使用线程安全的集合,例如CopyOnWriteArrayList,以避免并发问题。

因为该集合也实现了List接口,所以您只需要更改声明,就可以保持其余代码不变:

static List<String> foundDevicesArray = new CopyOnWriteArrayList<String> ();

最后,CopyOnWriteArrayList 通过在每次修改底层数组时复制底层数组来实现线程安全。如果您的数组经常被修改但竞争不激烈(您没有很多线程试图同时访问它),从内存使用的角度来看,同步列表可能是更好的选择 - 您应该同时尝试衡量性能与内存使用情况以做出明智的决定:

static List<String> foundDevicesArray =
                 Collections.synchronizedList(new ArrayList<String> ());
于 2013-02-04T18:02:46.880 回答