Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / Как ThreadPool переиспользует потоки? / 21 сообщений из 21, страница 1 из 1
15.02.2017, 18:29
    #39405202
questioner
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как ThreadPool переиспользует потоки?
Прочитал, что 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
15.02.2017, 18:55
    #39405218
questioner
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как ThreadPool переиспользует потоки?
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
15.02.2017, 22:25
    #39405311
no56892
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как ThreadPool переиспользует потоки?
questioner, ахахахах
Может стоит
Код: java
1.
2.
executorService.shutdown();
countDownLatch.await();


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

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

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

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

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

Код: 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
16.02.2017, 15:23
    #39405834
no56892
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как ThreadPool переиспользует потоки?
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
16.02.2017, 15:45
    #39405856
no56892
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как ThreadPool переиспользует потоки?
авторСделать comparable wrapper
Кстати, это не так просто сделать, т.е. сделать Comparable для объекта, который совсем не comparable... т.к. если тупо compareTo делать thread.getHashCode() - other.getHashCode() - а если два разных по identity треда будут иметь одинаковый хэшкод... Как вариант - static BigInteger счетчик в конструкторе Wrapper'a)).
...
Рейтинг: 0 / 0
16.02.2017, 15:53
    #39405867
no56892
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как ThreadPool переиспользует потоки?
no56892авторСделать comparable wrapper
Кстати, это не так просто сделать, т.е. сделать Comparable для объекта, который совсем не comparable... т.к. если тупо compareTo делать thread.getHashCode() - other.getHashCode() - а если два разных по identity треда будут иметь одинаковый хэшкод... Как вариант - static BigInteger счетчик в конструкторе Wrapper'a)).
Со счетчиком будет другая проблема - все врапперы будут разными, даже для одинаковых по identity тредов, т.е. остается вариант - использовать не SortedSet - CopyOnWriteArraySet, Collections.synchronized(new HashSet<>()).
...
Рейтинг: 0 / 0
16.02.2017, 15:56
    #39405873
questioner
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как ThreadPool переиспользует потоки?
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
16.02.2017, 15:56
    #39405875
Сергей Арсеньев
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как ThreadPool переиспользует потоки?
questionerА как Comparable связано с IMMUTABLE ?
Как HashMap ищет изменившийся объект знаешь?
Comparable тут совсем не причем.
...
Рейтинг: 0 / 0
16.02.2017, 16:02
    #39405881
questioner
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как ThreadPool переиспользует потоки?
Сергей АрсеньевquestionerА как Comparable связано с IMMUTABLE ?
Как HashMap ищет изменившийся объект знаешь?
Comparable тут совсем не причем.

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

Но последний тест вроде работает. Видимо в рамках этого теста immutable
...
Рейтинг: 0 / 0
16.02.2017, 16:05
    #39405887
questioner
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как ThreadPool переиспользует потоки?
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
16.02.2017, 16:06
    #39405889
Сергей Арсеньев
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как ThreadPool переиспользует потоки?
questioner,

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

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

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

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

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

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

Код: 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
Форумы / Java [игнор отключен] [закрыт для гостей] / Как ThreadPool переиспользует потоки? / 21 сообщений из 21, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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