Ошибка выполнения класса при запуске ExecutorService в Android Studio - PullRequest
0 голосов
/ 21 апреля 2019

У меня есть действие, которое использует AsyncTask для запуска сканирования. Во время метода doInbackground AsyncTask я вызываю исполняемый класс, который реализует Callable (мне нужно что-то вернуть из класса), этот класс устанавливает сокет-соединение с другими хостами, если соединение является успешным, тогда он пытается разрешить каноническое имя. И это имя хоста - это то, что я хочу получить из пула потоков. У меня проблема, когда я пытаюсь получить возврат из resultList.

public List<Future<Node>> resultList = new ArrayList<>();
public Future<Node> result = null;

Это исключение, которое я получаю. по-видимому, при использовании цикла for для обхода resultList для получения результатов. есть исключение приведения, поскольку я пытаюсь собрать неправильные данные.

 Caused by: java.lang.ClassCastException: java.util.ArrayList cannot be cast to org.pctechtips.netdroid.Node
            at org.pctechtips.netdroid.activity.IpScanActivity$TaskScanNetwork.doInBackground(IpScanActivity.java:202)
            at org.pctechtips.netdroid.activity.IpScanActivity$TaskScanNetwork.doInBackground(IpScanActivity.java:156)

Асинктаск класс

private class TaskScanNetwork extends AsyncTask<Void, Void, Void> {
        static final int NUMTHREADS = 254;
        String hostname;
        String subnet = ip.substring(0, ip.lastIndexOf("."));
        int startIp = 1;
        int range = (numOfHost / NUMTHREADS); //range to be scanned by every thread
        int stopIp = startIp + range;
        List<Future<Node>> resultList = new ArrayList<>();
        Future<Node> result = null;
        ExecutorService executor = Executors.newFixedThreadPool(NUMTHREADS);
        static final int TIME_OUT = 1000;


        @Override
        protected void onPreExecute() {
            hostList.clear();
            Node node = new Node(ip, mac);
            hostList.add(node);
            scanProgress.setMax(numOfHost);
            scanProgress.setProgress((numOfHost * 10) / 100 ); //set progress bar at 10%
//            statusMsg.setText("Scanning " + subnet + ".0/" + cidr);
        }

        /* initialaze threads */
        @Override
        protected Void doInBackground(Void... params) {
            Log.v("BACKGROUND", "doInBackground stuff");
            for(int i = 0; i < NUMTHREADS; i++) {
                IpScanRunnable ipScan = new IpScanRunnable(subnet, startIp, stopIp);
                result = executor.submit(ipScan);
                resultList.add(result);
                startIp = stopIp;
                stopIp = startIp + range;
            }

            try {
                new Thread().sleep(TIME_OUT);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }

            android.os.Debug.waitForDebugger();
            for(Future<Node> future : resultList) {
                try {
                    Log.v("NODE", future.get().getHostName());
                } catch (ExecutionException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }

            executor.shutdown();

            publishProgress();
            return null;
        }

        @Override
        protected void onProgressUpdate(Void... params) {
            networkAdapter.notifyDataSetInvalidated();
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            networkTxtView.setText(subnet + ".0/ " + cidr);
            numOfHostTxtView.setText(hosts+"");
            scanProgress.setProgress(254);
        }
    }

управляемый класс

package org.pctechtips.netdroid.runnable;
import org.pctechtips.netdroid.Node;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;

public class IpScanRunnable implements Callable {
    private List<Node> results;
    private static final String TAG = "IPSCANRUNNABLE";
    private final static int TIMEOUT = 1000;
    private final static int PORT = 7;

    private String subnet;
    private Integer startIp;
    private Integer stopIp;

    public IpScanRunnable(String subnet, int start, int stop) {
        this.subnet = subnet;
        this.startIp = start;
        this.stopIp = stop;
        results = new ArrayList();

    }

    @Override
    public List<Node> call() throws Exception {
        Socket socket = null;
        for(int i = startIp; i < stopIp; i++) {
            String ip = subnet + "." + i;
            socket = new Socket();
            try {
//                android.os.Debug.waitForDebugger();
                InetAddress ipAdd = InetAddress.getByName(ip);
                byte[] ipBytes = ipAdd.getAddress();
                socket.setTcpNoDelay(true);
                socket.connect(new InetSocketAddress(InetAddress.getByAddress(ipBytes), PORT), TIMEOUT);
                String hostname = ipAdd.getCanonicalHostName();
                Node node = new Node(ip);
                node.setHostName(hostname);
                results.add(node);
            }
            catch (Exception ex){

            }
        }
        return results;
    }

    public List<Node> getResults() {
        return results;
    }
}

1 Ответ

0 голосов
/ 21 апреля 2019

List<Node> call() возвращает список.Когда вы отправляете функцию callable исполнителю, она становится Future<List<Node>>, в то время как ваш список ожидает Future<Node>

Java не проверяет универсальный параметр во время выполнения, поэтому при добавлении Future<List<Node>> вместо Future<Node> ошибки не возникает.Тем не менее, когда вы получаете его из списка и приводите к Node, тогда оно терпит неудачу.

...