There is a code to work with threads.

ExecutorService threads = java.util.concurrent.Executors.newCachedThreadPool(); for (int i = 0; i < 10; i++) { // создаём поток threads.submit(new Runnable() { @Override public void run() { try { // какие-то инструкции потока } catch (Exception e) { } } }); } 

The question is inside the stream:

  1. pinging
  2. connect to ssh server
  3. execution of several commands on it.
    accordingly, this business takes some time, plus sometimes the server may not be available and the thread, respectively, runs longer than usual.

Required:

  1. run streams
  2. wait until all threads finish executing,
  3. continue with the main program.

Added by:
main ()

 ExecutorService threads = java.util.concurrent.Executors.newCachedThreadPool(); Future<String>[] tasks = new Future[servers.size()]; for (int i = 0; i < servers.size(); i++) { tasks[i] = threads.submit(new Thread_server(servers.get(i))); } while(checkThreads(tasks)) { try { Thread.sleep(1000); } catch (InterruptedException e) { } } threads.shutdown(); for (Future task : tasks) { try { System.out.println(task.get()); } catch (InterruptedException e) { } } 

checkThreads function

 private static boolean checkThreads(Future<String>[] tasks) { for (Future task : tasks) { if (!task.isDone()) { return true; } } return false; } 

class Thread_server

 public class Thread_server implements Callable { private Servers server = null; private String result = null; public Thread_server(Servers server) { this.server = server; } @Override public String call() { try { boolean ping = false; String host = null; if (server.getEnabled() == 1) { if (server.getVpnIp() != 0) { ping = true; host = new Libs().intToIp(server.getVpnIp()); } else { if (server.getGateIp()!= 0) { ping = true; host = new Libs().intToIp(server.getGateIp()); } } } if (ping) { InetAddress inet = InetAddress.getByName(host); boolean reachable = inet.isReachable(5000); if (reachable) { Ssh ssh = new Ssh(host); if (ssh.connect) { result = server.getName() + " - на связи (" + host + ") =>" + ssh.exec("uptime"); result = result + " Date:" + ssh.exec("date"); } else { result = server.getName() + " - НЕ на связи"; } ssh.sshDisconnect(); } else { result = server.getName() + " - НЕ на связи"; } } } catch (Exception e) { e.printStackTrace(); } finally { return result; } } } 

The problem is that if in the 1st version all servers responded, then in the last version, the non-responders receive null, but should not.

  • one
    Fine. What you can't do out of it? What have you tried? Look at Thread.start and Thread.join . - VladD
  • Future f = threads.submit (...); So ? but streams a lot - hitman249
  • one
    Well, remember them all in the list, the big deal! - VladD
  • another question, how else would the threads collect the answers in the same order? > where you can wait for the result with get. and how to indicate which of the entire stream object is the result? - hitman249
  • 2
    Well, run through the list of your future, tell everyone get, get a list of answers. At the same time and wait for the end of all. --- Well, pass Callable<T> , and not just Runnable . Get on exit Future<T> . - VladD

2 answers 2

InvokeAll starts several threads and waits for them to complete, so you can write something like this:

 ExecutorService pool = Executors.newCachedThreadPool(); List<Thread_server> tasks = new ArrayList<Thread_server>(); for (int i = 0; i < servers.size(); i++) { tasks.add(new Thread_server(servers.get(i))); // подготавливаем таски } List<Future<String>> answers = pool.invokeAll(tasks); // запустили, подождали и получили ответы pool.shutdown(); // если не нужен 
  • for some reason on pool.invokeAll (tasks); do not compile java: no suitable method for invokeAll (java.util.List <ru.pack.Thread_server>) method java.util.concurrent.ExecutorService. <T> invokeAll (java.util.Collection <? extends java.util. concurrent.Callable <T >>, long, java.util.concurrent.TimeUnit) method java.util.concurrent.ExecutorService. <T> invokeAll ( java.util.Collection <? extends java.util.concurrent.Callable <T >>) is not applicable - hitman249
  • but not, added <String> to Thread_server and compiled public class Thread_server implements Callable <String> - hitman249

We write something like this:

 ExecutorService threads = Executors.newCachedThreadPool(); List<Future<int>> tasks = new ArrayList<Future<int>>(); for (int i = 0; i < 10; i++) { tasks.add( threads.submit(new Callable<int>() { @Override public int call() { int result = 0; // что-то активно делаем return result; } })); } 

Wait for the end and collect the results:

 List<int> results = new ArrayList<int>(); for (Future<int> task : tasks) results.add(task.get()); 

Replace int with a real result type.

  • not everything works, added in the topic - hitman249
  • one
    And why do you need while (checkThreads (tasks)) {try {Thread.sleep (1000); } catch (InterruptedException e) {}} threads.shutdown (); ? He obviously does not need. --- And you need not Callable , but Callable<String> - VladD