Возможно ли вернуть переданный в Thread объект?

Например, передали объект Cats в Thread:

static List<Thread> threads = new ArrayList<Thread>(3);
void initThreads() {
  Cats cat = new Cats("cat");
  for (int i = 0; i < 3; i++) {
      threads.add(new Thread(cat, "#" + i));
  }
}

Можно вернуть объект Cats из threads[i]?


Ответы (2 шт):

Автор решения: lampa

Смотря что с котом будет происходить) Если нужно просто вернуть объект Cats, а у вас Cats это похоже что Runnable, то без танцев с бубном не получится получить Runnable из Thread. Варианты, например, через Map или рефлексию:

Map<Thread, Runnable> cats = new HashMap<>();

void initThreads() {
  Cats cat = new Cats("cat");
  for (int i = 0; i < 3; i++) {
     Thread thread = new Thread(cat, "#" + i);

     cats.put(thread, cat);
  }
}
...
cats.get(thread).getName();

Или если не хочется мапу, но такое лучше не использовать:

Thread thread = new Thread(new Cat("cat"), "123");
Field runnable = thread.getClass().getDeclaredField("runnable");
runnable.setAccessible(true);
Cat cat = (Cat) runnable.get(thread);

А если хочется дождаться результата, то нужно действовать по другому:

ExecutorService catExecutor = Executors.newSingleThreadExecutor();
List<Future<Cat>> futures = new ArrayList<>();

for (int i = 0; i < 5; i++) {
    final int index = i;

    final Future<Cats> future = catExecutor.submit(new Callable<Cat>() {
        @Override
        public Cats call() throws Exception {
            Thread.sleep(...);
            return new Cat("cat " + index);
        }
    });

    futures.add(future);
}

for (Future<Cats> f : futures) {
    try {
        System.out.println(f.get().getName());
    } catch (InterruptedException | ExecutionException ex) {
        ex.printStackTrace();
    }
}
→ Ссылка
Автор решения: Anastasiya
  1. Имплементировать для Cat интерфейс Runnable:
public class Cat implements Runnable {
  private String name;
  //getters setters constructor

  @Override
  public void run() {
    //some logic...
  }
}
  1. Понасоздавать экземпляров сколько влезет и подобавлять в список:
List<Cat> cats = IntStream.range(0, 3)
   .mapToObj(i -> new Cat("name#" + i))
   .collect(Collectors.toList());
  1. Создать экземпляр executorService и запустить каждый поток:
ExecutorService service = Executors.newCachedThreadPool();
cats.forEach(service::execute);

И все, пока они выполняются можете что-нибудь поделать с этим списком, например:

cats.stream()
  .map(Cat::getName)
  .forEach(System.out::println);

//Output: cat names...
→ Ссылка