Вернуть массив данных в основной класс из потоков
Пытаюсь получить список открытых портов в локальной сети, но без знания работы потоков это сложно. Не могу понять как извлечь данные из каждого потока и объединить их в массив для возврата в родительский класс. Пример кода ниже опрашивает хосты запуская проверку для каждого хоста в отдельном потоке и это работает в сотни раз быстрее чем делать запрос последовательно, но вот вернуть данные в Main класс у меня не выходит. Любая помощь или совет пригодятся мне.
public class Main {
public static void main(String[] args){
Scaner scaner = new Scaner();
scaner.scaner();
System.out.println("DONE!");
}
}
class Scaner {
private static final int TIMEOUT = 7000;
List<String> ip_list_with_open = new ArrayList<String>();
public void scaner(){
for (int i = 0; i<255; i++) {
String ip = "192.168.43."+i;
int port = 80;
Runnable task = () -> {
try {
Socket socket = new Socket();
SocketAddress address = new InetSocketAddress(ip,port);
socket.connect(address,TIMEOUT);
//OPEN
System.out.println(ip+":"+port+" = OPEN");
ip_list_with_open.add(ip);
socket.close();
} catch (UnknownHostException e) {
//WRONG ADRESS
System.out.println(ip+":"+port+" = WRONG ADRESS");
} catch (SocketTimeoutException e) {
//TIMEOUT
System.out.println(ip+":"+port+" = TIMEOUT");
} catch (IOException e) {
//CLOSED
System.out.println(ip+":"+port+" = CLOSED");
}
};
Thread thread = new Thread(task);
thread.start();
}
}
}
Ответы (2 шт):
Автор решения: Sergey Zh.
→ Ссылка
Runnable не возвращает результат, нужно использовать Callable
Подробнее об этом:
https://ru.stackoverflow.com/questions/811233/интерфейсы-runnable-и-callable
Автор решения: Roman
→ Ссылка
Тут нужно доделать 3 вещи:
- вы используете непотокобезопасную коллекцию
ArrayList, из-за этого при добавлении в неё элементов из разных тредов (потоков) результат непредсказуем. Надо заменить на потокобезопасную, например, обернуть вsynchronizedList:List<String> ip_list_with_open = Collections.synchronizedList(new ArrayList<>()); - вы не дожидаетесь окончания работы всех тредов. Надо их собрать в список (тут уже можно не потокобезопасный, т.к. работа с ним будет только из одного треда) и после завершения основного цикла сделать ещё один цикл, где пройтись по ним и для каждого вызвать
thread.join() - ну и чтобы вернуть результат, надо поменять тип возвращаемого значения у метода
scanerнаList<String>и в конце сделатьreturnвашего списка:
Тогда в методеpublic List<String> scaner() { //... return ip_list_with_open; }mainможно будет получить этот результат, типаList<String> ips = scaner.scaner();