powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Как ThreadPool переиспользует потоки?
21 сообщений из 21, страница 1 из 1
Как ThreadPool переиспользует потоки?
    #39405202
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Прочитал, что ThreadPool переиспользует потоки.
Я не очень понимаю как это происходит.

Создали мы 2 потока например и как их переиспользовать то? мы ж в конструкторе Runnable передаём.

Решил проверить кодом:

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
 public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        Set<Thread> threads = new HashSet<>();
        CountDownLatch countDownLatch = new CountDownLatch(5);
        for (int i = 0; i < 5; i++) {
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    threads.add(Thread.currentThread());
                    countDownLatch.countDown();

                }
            });
        }
        executorService.shutdown();
        countDownLatch.await();
        System.out.println("result: " + threads.size());
    }



Этот код выводит почти всегда 2, но иногда и 3.
...
Рейтинг: 0 / 0
Как ThreadPool переиспользует потоки?
    #39405218
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ooops

вот так надо:

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
 public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        Set<Thread> threads = new ConcurrentSkipListSet<>();
        CountDownLatch countDownLatch = new CountDownLatch(5);
        for (int i = 0; i < 5; i++) {
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    threads.add(Thread.currentThread());
                    countDownLatch.countDown();

                }
            });
        }
        executorService.shutdown();
        countDownLatch.await();
        System.out.println("result: " + threads.size());
    }



так вообще приложение зависает
...
Рейтинг: 0 / 0
Как ThreadPool переиспользует потоки?
    #39405311
no56892
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questioner, ахахахах
Может стоит
Код: java
1.
2.
executorService.shutdown();
countDownLatch.await();


местами поменять?
...
Рейтинг: 0 / 0
Как ThreadPool переиспользует потоки?
    #39405509
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
no56892,

а разве есть какая-то разница?
я думал те, что ещё в очереди будут обработаны, а новые не будут в нее добавляться
Теперь проблема в том, что Thread не Comparable. странно, что с HashSet приложение заканчивается, а с ConcurrentSkipListSet - нет. Причем странно первое.

надо с Collections.synchronizedSet проверить
...
Рейтинг: 0 / 0
Как ThreadPool переиспользует потоки?
    #39405552
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerТеперь проблема в том, что Thread не Comparable.
А ты уверен, что он IMMUTABLE, хотя бы в рамках hashCode()?
...
Рейтинг: 0 / 0
Как ThreadPool переиспользует потоки?
    #39405656
vimba
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerКак ThreadPool переиспользует потоки?

Вместо runnable который передал пользователь, тред инициализируется другим runnable, который не завершается пока пул не закрыли, ну или пока в пользовательской таске не произошел неперехваченный эксепшен, вот тред и крутится в цикле доставая из очереди задачки и засыпая пока их нет.
...
Рейтинг: 0 / 0
Как ThreadPool переиспользует потоки?
    #39405700
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сергей АрсеньевquestionerТеперь проблема в том, что Thread не Comparable.
А ты уверен, что он IMMUTABLE, хотя бы в рамках hashCode()?

А как Comparable связано с IMMUTABLE ?
...
Рейтинг: 0 / 0
Как ThreadPool переиспользует потоки?
    #39405743
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вот такой тест нормальный:

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
public class ThreadPoolTest {
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 10000; i++) {
            if (test() != 5000) {
                throw new RuntimeException("main");
            }
        }
    }

    private static long test() throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        CountDownLatch countDownLatch = new CountDownLatch(1000 * 5);
        Set<Thread> threads = Collections.synchronizedSet(new HashSet<>());
        AtomicLong atomicLong = new AtomicLong();
        for (int i = 0; i < 5 * 1000; i++) {
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        threads.add(Thread.currentThread());
                        atomicLong.incrementAndGet();
                        countDownLatch.countDown();
                    } catch (Exception e) {
                        System.out.println(e);
                    }


                }
            });
        }
        executorService.shutdown();
        countDownLatch.await();
        if (threads.size() != 2) {
            throw new RuntimeException("test");
        }
        return atomicLong.get();
    }
}
...
Рейтинг: 0 / 0
Как ThreadPool переиспользует потоки?
    #39405834
no56892
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerа разве есть какая-то разница?
я думал те, что ещё в очереди будут обработаны, а новые не будут в нее добавляться

Справедливо, че.

questionerТеперь проблема в том, что Thread не Comparable. странно, что с HashSet приложение заканчивается, а с ConcurrentSkipListSet - нет. Причем странно первое.

надо с Collections.synchronizedSet проверить

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
ExecutorService executor = Executors.newFixedThreadPool(2);
        Set<Thread> threads = new ConcurrentSkipListSet<>();
        CountDownLatch cdl = new CountDownLatch(5);
        for(int i = 0; i < 5; i++) {
            executor.execute(() -> {
                try {
                    threads.add(Thread.currentThread()); //(1)
                } finally {
                    cdl.countDown();
                }
            });
        }
        executor.shutdown();
        cdl.await();
        System.out.println(threads.size());


ConcurrentSkipListSet это аналог TreeSet, т.е. элементы д.б. Comparable, а вот аналог HashSet это CopyOnWriteArraySet. Соответственно, если добавить не Comparable элемент в SortedSet, то на строке (1) вылетает Exception и cdl.countDown() не выполняется и основной поток ждет бесконечно в cdl.await(). Варианта два - Сделать comparable wrapper для thread или использовать не SortedSet, например, CopyOnWriteArraySet.
...
Рейтинг: 0 / 0
Как ThreadPool переиспользует потоки?
    #39405856
no56892
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторСделать comparable wrapper
Кстати, это не так просто сделать, т.е. сделать Comparable для объекта, который совсем не comparable... т.к. если тупо compareTo делать thread.getHashCode() - other.getHashCode() - а если два разных по identity треда будут иметь одинаковый хэшкод... Как вариант - static BigInteger счетчик в конструкторе Wrapper'a)).
...
Рейтинг: 0 / 0
Как ThreadPool переиспользует потоки?
    #39405867
no56892
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
no56892авторСделать comparable wrapper
Кстати, это не так просто сделать, т.е. сделать Comparable для объекта, который совсем не comparable... т.к. если тупо compareTo делать thread.getHashCode() - other.getHashCode() - а если два разных по identity треда будут иметь одинаковый хэшкод... Как вариант - static BigInteger счетчик в конструкторе Wrapper'a)).
Со счетчиком будет другая проблема - все врапперы будут разными, даже для одинаковых по identity тредов, т.е. остается вариант - использовать не SortedSet - CopyOnWriteArraySet, Collections.synchronized(new HashSet<>()).
...
Рейтинг: 0 / 0
Как ThreadPool переиспользует потоки?
    #39405873
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
no56892no56892пропущено...

Кстати, это не так просто сделать, т.е. сделать Comparable для объекта, который совсем не comparable... т.к. если тупо compareTo делать thread.getHashCode() - other.getHashCode() - а если два разных по identity треда будут иметь одинаковый хэшкод... Как вариант - static BigInteger счетчик в конструкторе Wrapper'a)).
Со счетчиком будет другая проблема - все врапперы будут разными, даже для одинаковых по identity тредов, т.е. остается вариант - использовать не SortedSet - CopyOnWriteArraySet, Collections.synchronized(new HashSet<>()).

http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1250147&msg=20217787
...
Рейтинг: 0 / 0
Как ThreadPool переиспользует потоки?
    #39405875
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerА как Comparable связано с IMMUTABLE ?
Как HashMap ищет изменившийся объект знаешь?
Comparable тут совсем не причем.
...
Рейтинг: 0 / 0
Как ThreadPool переиспользует потоки?
    #39405881
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сергей АрсеньевquestionerА как Comparable связано с IMMUTABLE ?
Как HashMap ищет изменившийся объект знаешь?
Comparable тут совсем не причем.

ааа, ну да, тоже кстати проблема.

Но последний тест вроде работает. Видимо в рамках этого теста immutable
...
Рейтинг: 0 / 0
Как ThreadPool переиспользует потоки?
    #39405887
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
no56892questionerа разве есть какая-то разница?
я думал те, что ещё в очереди будут обработаны, а новые не будут в нее добавляться

Справедливо, че.

Сарказм?

тут вроде нет никаких проблем
questionerТеперь проблема в том, что Thread не Comparable. странно, что с HashSet приложение заканчивается, а с ConcurrentSkipListSet - нет. Причем странно первое.

надо с Collections.synchronizedSet проверить

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
ExecutorService executor = Executors.newFixedThreadPool(2);
        Set<Thread> threads = new ConcurrentSkipListSet<>();
        CountDownLatch cdl = new CountDownLatch(5);
        for(int i = 0; i < 5; i++) {
            executor.execute(() -> {
                try {
                    threads.add(Thread.currentThread()); //(1)
                } finally {
                    cdl.countDown();
                }
            });
        }
        executor.shutdown();
        cdl.await();
        System.out.println(threads.size());


ConcurrentSkipListSet это аналог TreeSet, т.е. элементы д.б. Comparable, а вот аналог HashSet это CopyOnWriteArraySet. Соответственно, если добавить не Comparable элемент в SortedSet, то на строке (1) вылетает Exception и cdl.countDown() не выполняется и основной поток ждет бесконечно в cdl.await(). Варианта два - Сделать comparable wrapper для thread или использовать не SortedSet, например, CopyOnWriteArraySet.


Я к тому, что если использовать HashSet в многопоточной среде велика вероятность, что случится какая-нить кака, например ConcurrentModificationException, но не случается
...
Рейтинг: 0 / 0
Как ThreadPool переиспользует потоки?
    #39405889
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questioner,

А чем тебя Thread.currentThread().getId() не устраивает?
...
Рейтинг: 0 / 0
Как ThreadPool переиспользует потоки?
    #39405899
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сергей Арсеньевquestioner,

А чем тебя Thread.currentThread().getId() не устраивает?

тем, что он может быть переиспользован после завершения потока
...
Рейтинг: 0 / 0
Как ThreadPool переиспользует потоки?
    #39405910
no56892
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторЯ к тому, что если использовать HashSet в многопоточной среде велика вероятность, что случится какая-нить кака, например ConcurrentModificationException, но не случается
Хмм, насколько я помню, ты спрашивал почему виснет с ConcurrentSkipSet и не виснет с HashSet. Это не связано с использованием HashSet в 2+ потоках на запись.
...
Рейтинг: 0 / 0
Как ThreadPool переиспользует потоки?
    #39405917
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сергей АрсеньевquestionerТеперь проблема в том, что Thread не Comparable.
А ты уверен, что он IMMUTABLE, хотя бы в рамках hashCode()?

equals/hashcode не переопределен в Thread.
Кстати тынц

hashCode будет привязан к месту в хипе, где объект создался. Но опять же это не гарантия, что коллизий не будет, но а equals, дефолтный вполне нормально работает. Так что в этом плане всё должно работать
...
Рейтинг: 0 / 0
Как ThreadPool переиспользует потоки?
    #39405923
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
no56892авторЯ к тому, что если использовать HashSet в многопоточной среде велика вероятность, что случится какая-нить кака, например ConcurrentModificationException, но не случается
Хмм, насколько я помню, ты спрашивал почему виснет с ConcurrentSkipSet и не виснет с HashSet. Это не связано с использованием HashSet в 2+ потоках на запись.

Да, я понял это несколько раньше просто, поэтому немного сместил акценты
...
Рейтинг: 0 / 0
Как ThreadPool переиспользует потоки?
    #39406012
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Отличный способ проверить то, что треды переиспользуются это так:

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
    public static void main(String[] args) throws InterruptedException {
        ThreadLocal<Integer> number = new ThreadLocal<Integer>() {
            private final AtomicInteger values = new AtomicInteger();

            @Override
            protected Integer initialValue() {
                return values.getAndIncrement();
            }
        };
        ExecutorService threadPool = Executors.newFixedThreadPool(100);


        for (int i = 0; i < 500; i++) {
            final int count = i;

            threadPool.submit(() -> System.out.printf("%-4s : %-20s - %s\n", count, Thread.currentThread().getName(), number.get()));
        }

        threadPool.shutdown();
        threadPool.awaitTermination(100, TimeUnit.SECONDS);

        System.out.println(number.get().intValue());
    }
...
Рейтинг: 0 / 0
21 сообщений из 21, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / Как ThreadPool переиспользует потоки?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]