Re[16]: Вопрос по кодонаписанию
От: Денис Цыплаков Россия  
Дата: 11.01.06 14:34
Оценка: 2 (2) +1
Blazkowicz пишет:

> ДЦ>Меня такая скорость устраивает.

>
> ИМХО, основные затраты производительности при создании большого
> количества временных объектов (коими является массив слушателей
> определенного типа) уходят на отработку GC, а не на само создание.

Я этот вопрос для себя изучал довольно тщательно. Дело в том, что
мы пишем софт для опроса различного рода устройств, а там задержки
могут быть очень критичны. Например в счетчиках электроэнергии
семейства ABB "Альфа" на авторизацию дается ~500 мс.
Причем надо проделать 2 транзакции запрос/ответ.

Соответственно я тщательно смотрел — где могут быть грабли. Не
хотелось попасть в ситуацию, когда софт сервера сбора написан на
Яве, а в силу ограничений на быстродействие его в принципе на Яве
написать нельзя.

Так вот. GC в современных Ява машинах
1. Довольно быстрый, плюс есть такая вещь как инкрементальный GC
коорый для многих задач решает проблему на корню.
2. Многопотоковый. Т.е. когда наступает GC тормозятся не все потоки,
а только тот которому надо памяти, соответсвенно если критичные
нити много пямяти не кушают, а в идеале вообще новых объектов не
создают, то GC их работу не тормозит.
3. Слухи про тормознутость Явы сильно преувеличены. Некоторые вещи
в ней работают быстрее чем в Си. Видимо за счет оптимизации при
JIT компиляции (правда таких вещей ОЧЕНЬ мало, но факт имеет место
быть)

Сама платформа как таковая работает довольно шустро. Мне для моих
довольно критичных ко времени задач — хватает. НО. Если решения
которые можно реализовать как на Яве, так и на Си, которые памяти
хотят много. И часто именно таким решениям приписывают тормоза.

Если изначально архитектура спроектированна так, что затратных
элементов в ней нет, то все будет работать быстро. При этом
мелкая оптимизация циклов, выделения памяти и т.п. не имеет большого
значения и ею можно и нужно пожертвовать в угоду удобочитаемости
кода и легкости последующей модификации проекта.

--
WBR Денис Цыплаков /* jabber UID: denis.tsyplakov@jabber.ru */
Знающий не говорит, говорящий не знает
Posted via RSDN NNTP Server 2.0
Re[18]: Вопрос по кодонаписанию
От: Денис Цыплаков Россия  
Дата: 11.01.06 15:32
Оценка: 6 (2)
Blazkowicz пишет:

> ДЦ> 2. Многопотоковый. Т.е. когда наступает GC тормозятся не все потоки,

> ДЦ> а только тот которому надо памяти, соответсвенно если критичные
> ДЦ> нити много пямяти не кушают, а в идеале вообще новых объектов не
> ДЦ> создают, то GC их работу не тормозит.
> Дык мы тут и имеем новые массивы при каждом обращении к методу. Выходит
> эти потоки все же будут блокироватся?

Дело в том, что релаьно сборка мусора может происходить в соседней
нити. А когда придет очередь нашей нити просить памяти — то у VM
уже будет N-цать мегабайт освобожденные пока ждала соседняя нить.

Это конечно как повезет, но в многопотоковой программе, сильно
облегчает жизнь.

Вот я тут сделал тестик иллюстрирующий работа GC. Тест на самом деле
не шибко показательный, т.к. объекты тут-же освобождаются и плюс
к тому, они одинакового размера, нет винигрега в куче. Но что-то
из него понять таки можно.

Тест запускался с опцией -Xmx1M т.е. JVM давался один мегабайт
памяти.
package ru.rtec.test.gc;

public class TestGC
{
     static long TEST_LENGTH = 15 * 1000;

     static int blockSize;

     public static void main(String[] args)
     {
         for (blockSize = 256; blockSize < 512 * 1024;
              blockSize = blockSize * 2)
         {
             System.out.println("---\nBlockSize: " + blockSize + " b");
             test();
         }
     }

     private static void test()
     {
         long maxTime = 0;
         long testStart = System.currentTimeMillis();
         long allocCount = 0;
         while (System.currentTimeMillis() - testStart < TEST_LENGTH)
         {
             long startCreate = System.currentTimeMillis();
             byte[] data = new byte[blockSize];
             long cLength = System.currentTimeMillis() - startCreate;
             data[0] = 1;//обманем оптимизатор на всякий случай.
             //16 мс - OS context switch
             if ((cLength!= 16)&&(cLength > maxTime))
             {
                 maxTime = cLength;
             }
             allocCount++;
         }
         System.out.println("Max time: " + maxTime + " ms");
         System.out.println("Allocation count: " + allocCount);
         System.out.println(
                 "Total allocated: " +
                         allocCount * blockSize / 1024 / 1024 + " Mb");
     }

}


Вот результаты

java -Xmx1M ru.rtec.test.gc.TestGC
---
BlockSize: 256 b
Max time: 16 ms
Allocation count: 31000048
Total allocated: 7568 Mb
---
BlockSize: 512 b
Max time: 32 ms
Allocation count: 19902126
Total allocated: 9717 Mb
---
BlockSize: 1024 b
Max time: 31 ms
Allocation count: 12387256
Total allocated: 12096 Mb
---
BlockSize: 2048 b
Max time: 31 ms
Allocation count: 6646271
Total allocated: 12980 Mb
---
BlockSize: 4096 b
Max time: 16 ms
Allocation count: 3564556
Total allocated: 13924 Mb
---
BlockSize: 8192 b
Max time: 31 ms
Allocation count: 1871281
Total allocated: 14619 Mb
---
BlockSize: 16384 b
Max time: 16 ms
Allocation count: 946896
Total allocated: 14795 Mb
---
BlockSize: 32768 b
Max time: 16 ms
Allocation count: 484477
Total allocated: 15139 Mb
---
BlockSize: 65536 b
Max time: 32 ms
Allocation count: 253517
Total allocated: 15844 Mb
---
BlockSize: 131072 b
Max time: 16 ms
Allocation count: 126876
Total allocated: 15859 Mb
---
BlockSize: 262144 b
Max time: 31 ms
Allocation count: 52479
Total allocated: 13119 Mb

Не забываем, что на 16 мс. время от времени процесс отрубается
Windows


--
WBR Денис Цыплаков /* jabber UID: denis.tsyplakov@jabber.ru */
Знающий не говорит, говорящий не знает
Posted via RSDN NNTP Server 2.0
Re[3]: Вопрос по кодонаписанию
От: Airat Burganov Россия http://www.burganov.com
Дата: 10.01.06 12:57
Оценка: -1 :)
Т>да, точно Multicast как же я это забыл
интересно, как это вы могли это помнить? dshe только представил реализацию, а вы уже о ней в курсе
Re[4]: Вопрос по кодонаписанию
От: dshe  
Дата: 10.01.06 13:29
Оценка: 5 (1)
Здравствуйте, Airat Burganov, Вы писали:

D>>То они в равной степени предоставляют "структурную" информацию. Оба эти варианта говорят о том, что comp позволяет подписаться на определенное событие.

AB>(Не касаясь того, как это будет реализованно)
AB>Да.. структурно. Но вас не смущает то, что onComponentEvent — public переменная?

Немного смущает. Впрочем, можно заменить прямой доступ к переменной вызовом метода. Также, поскольку в той моей оригинальной реализации метод fire() будет "светиться" подписчикам, думаю, что имело бы смысл выделить интерфейс для подписки
public interface Subscription<T> {
    public void add(T o);
    public void remove(T o);
}

public final class Multicast<T> implements Subscription<T> {
    // . . .
}

И вот уже после этого сделать метод, который возвращает Subscription<T>, а не Multicast<T>.
    protected final Multicast<ComponentListener> onComponentEventMulticast = Multicast.create(ComponentListener.class);
    public Subscription<ComponentListener> onComponentEvent() {
        return onComponentEventMulticast;
    }


D>>Однако, если реализовать подписку классическим вариантом, то можно заметить, что много кода буквально дублируется. Код подписки для различных listener'ов похож до безобразия. Поэтому было бы неплохо его написать один раз и потом использовать (а не переписывать для каждого типа listener'а заново).

AB>Вот это действительно очень надоедливая штука. Правда есть EventListenerList, который во-многом позволяет смириться с этим.

К сожалению, EventListenerList не освобождает от необходимости переписывать каждый раз
 protected void fireFooXXX() {
     // Guaranteed to return a non-null array
     Object[] listeners = listenerList.getListenerList();
     // Process the listeners last to first, notifying
     // those that are interested in this event
     for (int i = listeners.length-2; i>=0; i-=2) {
         if (listeners[i]==FooListener.class) {
             // Lazily create the event:
             if (fooEvent == null)
                 fooEvent = new FooEvent(this);
             ((FooListener)listeners[i+1]).fooXXX(fooEvent);
         }
     }
 }
--
Дмитро
Вопрос по кодонаписанию
От: Тычеблин Китай  
Дата: 08.01.06 04:13
Оценка: 4 (1)
Привет Всем

Сначала думал оформить в контексте Вопрос по правильному кодонаписанию
Автор: leska
Дата: 06.01.06
потом передумал. У меня вопрос тоже по стилю но о другом.

Предлагаю обсудить то, как можно было бы более правильно и красиво реализовать подписку на собылия объекта и отказ от них.
то как это сделано в AWT/SWING например у Component
    public synchronized void addComponentListener(ComponentListener l)
    public synchronized void removeComponentListener(ComponentListener l)
    public synchronized ComponentListener[] getComponentListeners()

    public synchronized void addFocusListener(FocusListener l)
    public synchronized void removeFocusListener(FocusListener l)
    public synchronized FocusListener[] getFocusListeners()

    public void addHierarchyListener(HierarchyListener l)
    public void removeHierarchyListener(HierarchyListener l)
    public synchronized HierarchyListener[] getHierarchyListeners()

    public void addHierarchyBoundsListener(HierarchyBoundsListener l)
    public void removeHierarchyBoundsListener(HierarchyBoundsListener l)
    public synchronized HierarchyBoundsListener[] getHierarchyBoundsListeners()

    public synchronized void addKeyListener(KeyListener l)
    public synchronized void removeKeyListener(KeyListener l)
    public synchronized KeyListener[] getKeyListeners()

    public synchronized void addMouseListener(MouseListener l)
    public synchronized void removeMouseListener(MouseListener l)
    public synchronized MouseListener[] getMouseListeners()

    public synchronized void addMouseMotionListener(MouseMotionListener l)
    public synchronized void removeMouseMotionListener(MouseMotionListener l)
    public synchronized MouseMotionListener[] getMouseMotionListeners()

    public synchronized void addMouseWheelListener(MouseWheelListener l)
    public synchronized void removeMouseWheelListener(MouseWheelListener l)
    public synchronized MouseWheelListener[] getMouseWheelListeners()

    public synchronized void addInputMethodListener(InputMethodListener l)
    public synchronized void removeInputMethodListener(InputMethodListener l)
    public synchronized InputMethodListener[] getInputMethodListeners()

лично я нахожу откровенно корявым и загаживающим API. (нет? )

более элегантным решением могло бы стать что-то вроди
    public ComponentListener.Hub onComponentEvent=....
    public FocusListener.Hub onFocusEvent=....
    public HierarchyListener.Hub onHierarchyEvent=....

........

        public interface ComponentListener extends EventListener
    {
        public void componentResized(ComponentEvent e);
        public void componentMoved(ComponentEvent e);
        public void componentShown(ComponentEvent e);
        public void componentHidden(ComponentEvent e);
        
        public class Hub
        {
            public void add(ComponentListener c){};
            public void del(ComponentListener c){};
            public ComponentListener get(){};
        }
        
    }
........

таким образом использование будет выглядить так
......
comp.onComponentEvent.add(componentListener);//добавление обработчика
comp.onComponentEvent.del(componentListener);//удаление обработчика
comp.onComponentEvent.get().componentShown(componentEvent);//вызов (invoke) у всех зарег. обработчиков componentShown(ComponentEvent e)
.....

Но (!) как это может быть устроено внутри? что думаете?
Re[3]: Вопрос по кодонаписанию
От: Airat Burganov Россия http://www.burganov.com
Дата: 10.01.06 12:53
Оценка: 1 (1)
D>Вообще-то, не мешало бы уточнить, чем именно опасны непосредственные связи и от чего правило Деметры предохраняет. Насколько я понимаю, правилу Деметры необходимор следовать для того, чтобы информация о "структурных" деталях реализации одного класса не расползалась по всей системе (приложению). Что же касается двух вариантов подписки
D>1. классический
D>
D>comp.addComponentListener(componentListener);
D>comp.removeComponentListener(componentListener);
D>comp.fireComponentShown(componentEvent);
D>

D>2. "хитрый"
D>
D>comp.onComponentEvent.add(componentListener);
D>comp.onComponentEvent.del(componentListener);
D>comp.onComponentEvent.get().componentShown(componentEvent);
D>


D>То они в равной степени предоставляют "структурную" информацию. Оба эти варианта говорят о том, что comp позволяет подписаться на определенное событие.

(Не касаясь того, как это будет реализованно)
Да.. структурно. Но вас не смущает то, что onComponentEvent — public переменная?

D>Однако, если реализовать подписку классическим вариантом, то можно заметить, что много кода буквально дублируется. Код подписки для различных listener'ов похож до безобразия. Поэтому было бы неплохо его написать один раз и потом использовать (а не переписывать для каждого типа listener'а заново).

Вот это действительно очень надоедливая штука. Правда есть EventListenerList, который во-многом позволяет смириться с этим.
Re[5]: Вопрос по кодонаписанию
От: Тычеблин Китай  
Дата: 11.01.06 13:42
Оценка: 1 (1)
Здравствуйте, dshe, Вы писали:

D>Пример: Один разработчик для какого-то своего типа события FOO зарезервировал константу (1<<8), и другой разработчик, ничего не зная о первом, уже для своего события BAR зарезервировал константу (1<<8). В результате этого получается, что одновременно использовать события FOO и BAR невозможно из-за коллизии констант. Мой вопрос был о том, как избежать подобной ситуации?


предполагаю, что там события контекстны. чтобы быть более понятным
addKeyListener(IKeyListener.KeyPress | IKeyListener.KeyTyped | IKeyListener.KeyRelease, IKeyListener l)
addMouseListener(IMouseListener.MouseEnter| IMouseListener.MouseExit | IMouseListener.MouseMove, IMouseListener l)
Re[3]: Вопрос по кодонаписанию
От: Blazkowicz Россия  
Дата: 11.01.06 13:44
Оценка: 1 (1)
Здравствуйте, dshe, Вы писали:

D>А что делать, когда констант не хватит?

Сложный вопрос. Мне кажется что в SWT он решен тем что написание собственных виджетов на столько трудоемко что этим никто не занимается. к тому же набор низкоуровневых событий UI ограничен.


D>И как контролировать то, что одна и те же константа не используется для разных целей?

Оу, ну для этого достаточно все константы хранить в одном классе. В SWT он так и называется: SWT.
Re: Вопрос по кодонаписанию
От: Blazkowicz Россия  
Дата: 10.01.06 09:40
Оценка: +1
Здравствуйте, Тычеблин, Вы писали:

Т>Сначала думал оформить в контексте Вопрос по правильному кодонаписанию
Автор: leska
Дата: 06.01.06
потом передумал. У меня вопрос тоже по стилю но о другом.


Т>Предлагаю обсудить то, как можно было бы более правильно и красиво реализовать подписку на собылия объекта и отказ от них.

Т>то как это сделано в AWT/SWING например у Component

Т>таким образом использование будет выглядить так

comp.onComponentEvent.add(componentListener);//добавление обработчика
comp.onComponentEvent.del(componentListener);//удаление обработчика
comp.onComponentEvent.get().componentShown(componentEvent);//вызов (invoke) у всех зарег. обработчиков

Т>Но (!) как это может быть устроено внутри? что думаете?

Уж не делегаты ли из C# вы нам пытаетесь подсунуть?
Re[3]: Вопрос по кодонаписанию
От: Тычеблин Китай  
Дата: 10.01.06 12:17
Оценка: :)
Здравствуйте, dshe, Вы писали:

D>Однако, если реализовать подписку классическим вариантом, то можно заметить, что много кода буквально дублируется. Код подписки для различных listener'ов похож до безобразия. Поэтому было бы неплохо его написать один раз и потом использовать (а не переписывать для каждого типа listener'а заново).


спасибо дружище за понимание, а то, получая бессмысленные ответы на вопросы которых я не задавал, я уже начал сомневаться в своей способности объяснять
Re: Вопрос по кодонаписанию
От: Airat Burganov Россия http://www.burganov.com
Дата: 08.01.06 08:34
Оценка:
Т>Предлагаю обсудить то, как можно было бы более правильно и красиво реализовать подписку на собылия объекта и отказ от них.
Т>то как это сделано в AWT/SWING например у Component
Т>лично я нахожу откровенно корявым и загаживающим API. (нет? )

Т>более элегантным решением могло бы стать что-то вроди

T> что думаете?

Мне больше нравится стандартное решение.
Кроме того ваше решение противоречит т.н. правилу Деметры, упоминание о котором можно встретить в книжке
С. Макконела "Совершенный код" (глава 6.3)

Избегайте опосредованных вызовов методов других классов.
Непосредственные связи довольно опасны. Опосредованные связи, такие как account.ContactPerson().DaytimeContactlnfo().PhoneNumberO, опасны еще больше. В связи с этим ученые сформулировали «Правило Деметры (Law of Demeter)» (Lieberherr and Holland, 1989), которое гласит, что Объект А может вызывать любые из собственнных методов. Если он создает Объект В, он может вызывать любые методы Объекта В, но ему не следует вызывать методы объектов, возвращаемых Объектом В. В нашем случае это означает, что вызов account.ContactPerson() приемлем, однако вызова account.ContactPerson().DaytimeContactlnfo() следовало бы избежать.

Re[2]: Вопрос по кодонаписанию
От: Тычеблин Китай  
Дата: 08.01.06 09:06
Оценка:
Здравствуйте, Airat Burganov, Вы писали:

AB>Мне больше нравится стандартное решение.


тем что оно именно стандартное? это безусловно сильный аргумент, не поспоришь. но на этом мне видимые плюсы заканчиваются.

AB>Кроме того ваше решение противоречит т.н. правилу Деметры,


ну, в общем без проблем, если хочется чему-то удовлетворять или соответствовать, можно и через промежуточную переменную.
//а мине вот так писать ндравилось фсигда ;) 
new Thread()
{
    public void run()
    {
        asych_call();
    }

}.start();

только прошу понять меня правильно, я ведь не умничать пытаюсь.
просто предлагаю тем, кому это интересно совместно задуматься, исследовать эту проблемму.
Re[3]: Вопрос по кодонаписанию
От: Airat Burganov Россия http://www.burganov.com
Дата: 08.01.06 09:51
Оценка:
AB>>Мне больше нравится стандартное решение.

Т>тем что оно именно стандартное? это безусловно сильный аргумент, не поспоришь. но на этом мне видимые плюсы заканчиваются.

Я честно говоря у вашего решения плюсов не вижу. В плане реализации писать надо не меньше. Интуитивно не понятно. Какие у вас плюсы? Минусы — введение дополнительных сущностей Hub на какждый новый листенер, не прозрачная иерархия вызовов.

AB>>Кроме того ваше решение противоречит т.н. правилу Деметры,

Т>ну, в общем без проблем, если хочется чему-то удовлетворять или соответствовать, можно и через промежуточную переменную.
Да нет, можно и не соответсвовать, к тому же правило малоизвестное. Но почему-то обычно когда я вижу в коде множество вызовов, например таких
myFrame.myTable.getModel().getRow().getЧтонибудьеще()

то вскоре оказывается, что микроархитектура этого кода очень кривая.
Re[4]: Вопрос по кодонаписанию
От: Тычеблин Китай  
Дата: 08.01.06 10:59
Оценка:
Здравствуйте, Airat Burganov, Вы писали:

AB>Я честно говоря у вашего решения плюсов не вижу. В плане реализации писать надо не меньше. Интуитивно не понятно. Какие у вас плюсы? Минусы — введение дополнительных сущностей Hub на какждый новый листенер, не прозрачная иерархия вызовов.


я честно полагаю, что вы прочли мой изначальный пост, но я в силу кривости моего изложения был вами непонят. попробую еще раз.

вместо
    public synchronized void addComponentListener(ComponentListener l)
    public synchronized void removeComponentListener(ComponentListener l)
    public synchronized ComponentListener[] getComponentListeners()

будет в API объекта генерирующего события останется только
    public ComponentListener.Hub onComponentEvent=....

onComponentEvent — сущность, функцией которой является регистрация получателей собылтий.
благодоря ей происходит очистка API объекта от утилитарных методов
AB>Но почему-то обычно когда я вижу в коде множество вызовов, например таких
AB>
AB>myFrame.myTable.getModel().getRow().getЧтонибудьеще()
AB>

AB>то вскоре оказывается, что микроархитектура этого кода очень кривая.

причем тут архитектура? то о чем Вы говорите — это уже использование некоторой архитектуры.
такую последовательность вызовов несможет предотвратить ни одна архитектура, ну, кроме разве той, согласно которой методу запрещено возвращать ссылку на объект. но это не идеология JAVA, вроди так
Re[5]: Вопрос по кодонаписанию
От: Airat Burganov Россия http://www.burganov.com
Дата: 08.01.06 11:34
Оценка:
AB>>Я честно говоря у вашего решения плюсов не вижу. В плане реализации писать надо не меньше. Интуитивно не понятно. Какие у вас плюсы? Минусы — введение дополнительных сущностей Hub на какждый новый листенер, не прозрачная иерархия вызовов.

Т>я честно полагаю, что вы прочли мой изначальный пост, но я в силу кривости моего изложения был вами непонят. попробую еще раз.


Т>вместо

Т>
Т>    public synchronized void addComponentListener(ComponentListener l)
Т>    public synchronized void removeComponentListener(ComponentListener l)
Т>    public synchronized ComponentListener[] getComponentListeners()
Т>

для демонстрации synchronized или надо было убирать, либо делать synchronized и свое api.

Т>будет в API объекта генерирующего события останется только

Т>
Т>    public ComponentListener.Hub onComponentEvent=....
Т>

Т>onComponentEvent — сущность, функцией которой является регистрация получателей собылтий.
Т>благодоря ей происходит очистка API объекта от утилитарных методов
Пожалуйста более подробнее. И ответьте в чем польза использования именно такого объекта. Где плюсы? Упомянутые мною минусы сохраняются и не объяснены. Ваша реализация непрозрачная. Как написать addComponentListener, removeComponentListener, getComponentListeners в 6-8 строк я знаю, а как писать ваш листенер?
  public interface ComponentListener extends EventListener
    {
        public void componentResized(ComponentEvent e);
        public void componentMoved(ComponentEvent e);
        public void componentShown(ComponentEvent e);
        public void componentHidden(ComponentEvent e);
        
        public class Hub
        {
            public void add(ComponentListener c){};
            public void del(ComponentListener c){};
            public ComponentListener get(){};
        }
        
    }

Насколько я понимаю меоды add,del,get реализуются в интерфейсе? а инкапсуляция? А если я закочу расширить этот компонент листенер, всюду делать свои hub'ы? Ни о чем этом вы похоже не думали.

Ссылки на то, что главное — это идея не принимаются. Идеи никакой тут нет, одна бессмыслица, набор необоснованных утверждений. Вы сами пробовали пользоваться тем, что написали? Хоть один реальный листенер покажите.

Т>причем тут архитектура? то о чем Вы говорите — это уже использование некоторой архитектуры.

Т>такую последовательность вызовов несможет предотвратить ни одна архитектура, ну, кроме разве той, согласно которой методу запрещено возвращать ссылку на объект. но это не идеология JAVA, вроди так
микроархитектура. Паттерны спасут.
Re[6]: Вопрос по кодонаписанию
От: Тычеблин Китай  
Дата: 08.01.06 12:47
Оценка:
Здравствуйте, Airat Burganov, Вы писали:

AB>микроархитектура. Паттерны спасут.


несколько раз перечитал Ваши ответы, долго думал.
Вы либо не внимательны либо я совсем плохо объясняю.
Re[2]: Вопрос по кодонаписанию
От: Тычеблин Китай  
Дата: 10.01.06 10:19
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>Здравствуйте, Тычеблин, Вы писали:


Т>>Сначала думал оформить в контексте Вопрос по правильному кодонаписанию
Автор: leska
Дата: 06.01.06
потом передумал. У меня вопрос тоже по стилю но о другом.


Т>>Предлагаю обсудить то, как можно было бы более правильно и красиво реализовать подписку на собылия объекта и отказ от них.

Т>>то как это сделано в AWT/SWING например у Component

Т>>таким образом использование будет выглядить так

B>
B>comp.onComponentEvent.add(componentListener);//добавление обработчика
B>comp.onComponentEvent.del(componentListener);//удаление обработчика
B>comp.onComponentEvent.get().componentShown(componentEvent);//вызов (invoke) у всех зарег. обработчиков

Т>>Но (!) как это может быть устроено внутри? что думаете?

B>Уж не делегаты ли из C# вы нам пытаетесь подсунуть?


неа. оно конечно внешне (текстово) похоже on(ля-ля-ля)Event. но конечно это не делегаты, это больше попытка очистить API от разнообразных утилитарных методов имеющих отношение не столько к самому объекту, а к процессу регистрации обработчиков сбытий объекта.
к стати уже кой чего наизобретал, если сочту это не смешным и жизнеспособным выложу, отпинайте
Re[3]: Вопрос по кодонаписанию
От: Lucker Беларусь http://lucker.intervelopers.com/
Дата: 10.01.06 10:25
Оценка:
Здравствуйте, Тычеблин, Вы писали:

B>>Уж не делегаты ли из C# вы нам пытаетесь подсунуть?


Т>неа. оно конечно внешне (текстово) похоже on(ля-ля-ля)Event. но конечно это не делегаты, это больше попытка очистить API от разнообразных утилитарных методов имеющих отношение не столько к самому объекту, а к процессу регистрации обработчиков сбытий объекта.

Ну по этому поводу изобретать ничего не стоит, тем более что это что-то практически настолько-же прямое, насколько иоригинальное решение. Имя этим (как и многим другим) "утилитарным методам" — аспекты. Методы работы с аспектами, и конкретные реалиизации АОП (аспектно-ориентированного программирования) для java есть (например, aspectJ) и успешно применяются. Так что думаю если и рыть куда — то именно туда.
#333355130
Re[3]: Вопрос по кодонаписанию
От: Blazkowicz Россия  
Дата: 10.01.06 10:26
Оценка:
Здравствуйте, Тычеблин, Вы писали:

Т>неа. оно конечно внешне (текстово) похоже on(ля-ля-ля)Event. но конечно это не делегаты

Ну а делегаты "внутренне" это слушатели в Java. Так в чем внутреннее различие того что предолжено с делагатами?

Т>это больше попытка очистить API от разнообразных утилитарных методов имеющих отношение не столько к самому объекту, а к процессу регистрации обработчиков сбытий объекта.

Ну а делегаты не тоже ли самое?

Т>к стати уже кой чего наизобретал, если сочту это не смешным и жизнеспособным выложу, отпинайте

Ждем с нетерпением.
Re[4]: Вопрос по кодонаписанию
От: Тычеблин Китай  
Дата: 10.01.06 10:39
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>Здравствуйте, Тычеблин, Вы писали:


Т>>неа. оно конечно внешне (текстово) похоже on(ля-ля-ля)Event. но конечно это не делегаты

B>Ну а делегаты "внутренне" это слушатели в Java. Так в чем внутреннее различие того что предолжено с делагатами?

Т>>это больше попытка очистить API от разнообразных утилитарных методов имеющих отношение не столько к самому объекту, а к процессу регистрации обработчиков сбытий объекта.

B>Ну а делегаты не тоже ли самое?

впервые столкнувшись с делигатами в Visual Java 6.0( к стати класная фича) я понял что делигаты это попытка решения обширного числа проблемм.
то что происходит очистка API от утилитарных методов подписки и удаления обработчиков событий (тема топика) это далеко не самое главное — так, побочный продукт (конечно нужный).

главное это возможность передачи указателя на метод сигнатура которого соответствует требуемому.
и не важно ни название метода не область видимости. сейчас вспоминая войну сана и микрософта на эту тему понимаешь какие сановцы были неадекватно воинствующие. особенно глядя на те изменения которые они же внесли в JDK 1.5. лучше б делигаты добавили
Re[5]: Вопрос по кодонаписанию
От: Blazkowicz Россия  
Дата: 10.01.06 10:50
Оценка:
Здравствуйте, Тычеблин, Вы писали:

Т>впервые столкнувшись с делигатами в Visual Java 6.0( к стати класная фича) я понял что делигаты это попытка решения обширного числа проблемм.

Т>то что происходит очистка API от утилитарных методов подписки и удаления обработчиков событий (тема топика) это далеко не самое главное — так, побочный продукт (конечно нужный).
Прошу прощения за снобизм, но все же "делегат", и уж никак не "Visual Java 6.0", а скорее всего
"Visual J++ 6.0"

Т>главное это возможность передачи указателя на метод сигнатура которого соответствует требуемому.

Дык тут, ИМХО без рефлексии, либо аспектов не обойтись.

Т>и не важно ни название метода не область видимости. сейчас вспоминая войну сана и микрософта на эту тему понимаешь какие сановцы были неадекватно воинствующие. особенно глядя на те изменения которые они же внесли в JDK 1.5. лучше б делигаты добавили

Гугл по вопросу делегатов в Java выдаёт довольно много ссылок. Видел даже какую-то реализацию через аннотации.
Re: Вопрос по кодонаписанию
От: dshe  
Дата: 10.01.06 11:20
Оценка:
Здравствуйте, Тычеблин, Вы писали:

Т>Привет Всем


Т>Сначала думал оформить в контексте Вопрос по правильному кодонаписанию
Автор: leska
Дата: 06.01.06
потом передумал. У меня вопрос тоже по стилю но о другом.


Т>таким образом использование будет выглядить так

Т>
Т>......
Т>comp.onComponentEvent.add(componentListener);//добавление обработчика
Т>comp.onComponentEvent.del(componentListener);//удаление обработчика
Т>comp.onComponentEvent.get().componentShown(componentEvent);//вызов (invoke) у всех зарег. обработчиков componentShown(ComponentEvent e)
Т>.....
Т>

Т>Но (!) как это может быть устроено внутри? что думаете?

Я тоже задумывался об этом. У меня получилось такое
package muticast;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

/**
 * @author dshe
 *
 */
public final class Multicast<T> {
    private static final Map<Class<?>, Object> DEF_VALUES_CLASS_TO_OBJECT;
    static {
        DEF_VALUES_CLASS_TO_OBJECT = new HashMap<Class<?>, Object>();
        DEF_VALUES_CLASS_TO_OBJECT.put(boolean.class, Boolean.FALSE);
        DEF_VALUES_CLASS_TO_OBJECT.put(byte.class, new Byte((byte) 0));
        DEF_VALUES_CLASS_TO_OBJECT.put(short.class, new Short((short) 0));
        DEF_VALUES_CLASS_TO_OBJECT.put(char.class, new Character('\0'));
        DEF_VALUES_CLASS_TO_OBJECT.put(int.class, new Integer(0));
        DEF_VALUES_CLASS_TO_OBJECT.put(long.class, new Long(0L));
        DEF_VALUES_CLASS_TO_OBJECT.put(float.class, new Float(0f));
        DEF_VALUES_CLASS_TO_OBJECT.put(double.class, new Double(0d));
    }

    class Handler implements InvocationHandler {
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object[] array = _list.toArray();
            Throwable thrown = null;
            for(int i = 0, n = array.length; i < n; ++i) {
                try {
                    method.invoke(array[i], args);
                }
                catch(IllegalAccessException exc) {
                    throw (Error) new IllegalAccessError().initCause(exc);
                }
                catch(InvocationTargetException exc) {
                    thrown = exc.getTargetException();
                }
            }
            // rethrow last occured exception
            if(thrown != null)
                throw thrown;
            // we cannot return null if method returns primitive value
            // thus we lookup default value is a table.
            return DEF_VALUES_CLASS_TO_OBJECT.get(method.getReturnType());
        }
    }

    private final List<T> _list;
    private final Class<T> _iface;
    private final T _proxy;

    private Multicast(Class<T> iface) {
        _list = new Vector<T>();
        _iface = iface;
        // unchecked cast: dont worry
        _proxy = (T) Proxy.newProxyInstance(iface.getClassLoader(), new Class[] { iface }, new Handler());
    }

    // static factory method is just for convenient type inference
    public static <U> Multicast<U> create(Class<U> iface) {
        return new Multicast<U>(iface);
    }

    public T fire() {
        return _proxy;
    }

    public void add(T obj) {
        if(!_iface.isInstance(obj))
            throw new IllegalArgumentException("obj : " + obj);
        _list.add(obj);
    }

    public void remove(T obj) {
        if(!_iface.isInstance(obj))
            throw new IllegalArgumentException("obj : " + obj);
        _list.remove(obj);
    }
}


И использование (имена методов, правда, немного поменял)
        Multicast<Runnable> multicast = Multicast.create(Runnable.class);
        Runnable a = new Runnable() {
            public void run() {
                System.out.println("one");
            }
        };
        Runnable b = new Runnable() {
            public void run() {
                System.out.println("two");
            }
        };
        multicast.add(a);
        multicast.add(b);
        multicast.fire().run();
        multicast.remove(b);
        multicast.fire().run();
--
Дмитро
Re[2]: Вопрос по кодонаписанию
От: dshe  
Дата: 10.01.06 11:40
Оценка:
Здравствуйте, Airat Burganov, Вы писали:

Т>>Предлагаю обсудить то, как можно было бы более правильно и красиво реализовать подписку на собылия объекта и отказ от них.

Т>>то как это сделано в AWT/SWING например у Component
Т>>лично я нахожу откровенно корявым и загаживающим API. (нет? )

Т>>более элегантным решением могло бы стать что-то вроди

T>> что думаете?

AB>Мне больше нравится стандартное решение.

AB>Кроме того ваше решение противоречит т.н. правилу Деметры, упоминание о котором можно встретить в книжке
AB>С. Макконела "Совершенный код" (глава 6.3)
AB>

AB>Избегайте опосредованных вызовов методов других классов.
AB>Непосредственные связи довольно опасны. Опосредованные связи, такие как account.ContactPerson().DaytimeContactlnfo().PhoneNumberO, опасны еще больше. В связи с этим ученые сформулировали «Правило Деметры (Law of Demeter)» (Lieberherr and Holland, 1989), которое гласит, что Объект А может вызывать любые из собственнных методов. Если он создает Объект В, он может вызывать любые методы Объекта В, но ему не следует вызывать методы объектов, возвращаемых Объектом В. В нашем случае это означает, что вызов account.ContactPerson() приемлем, однако вызова account.ContactPerson().DaytimeContactlnfo() следовало бы избежать.


Вообще-то, не мешало бы уточнить, чем именно опасны непосредственные связи и от чего правило Деметры предохраняет. Насколько я понимаю, правилу Деметры необходимор следовать для того, чтобы информация о "структурных" деталях реализации одного класса не расползалась по всей системе (приложению). Что же касается двух вариантов подписки
1. классический
comp.addComponentListener(componentListener);
comp.removeComponentListener(componentListener);
comp.fireComponentShown(componentEvent);

2. "хитрый"
comp.onComponentEvent.add(componentListener);
comp.onComponentEvent.del(componentListener);
comp.onComponentEvent.get().componentShown(componentEvent);


То они в равной степени предоставляют "структурную" информацию. Оба эти варианта говорят о том, что comp позволяет подписаться на определенное событие.

Однако, если реализовать подписку классическим вариантом, то можно заметить, что много кода буквально дублируется. Код подписки для различных listener'ов похож до безобразия. Поэтому было бы неплохо его написать один раз и потом использовать (а не переписывать для каждого типа listener'а заново).
--
Дмитро
Re[2]: Вопрос по кодонаписанию
От: Тычеблин Китай  
Дата: 10.01.06 12:21
Оценка:
Здравствуйте, dshe, Вы писали:

D
D>И использование (имена методов, правда, немного поменял)
D>
D>        Multicast<Runnable> multicast = Multicast.create(Runnable.class);
D>        Runnable a = new Runnable() {
D>            public void run() {
D>                System.out.println("one");
D>            }
D>        };
D>        Runnable b = new Runnable() {
D>            public void run() {
D>                System.out.println("two");
D>            }
D>        };
D>        multicast.add(a);
D>        multicast.add(b);
D>        multicast.fire().run();
D>        multicast.remove(b);
D>        multicast.fire().run();
D>


да, точно Multicast как же я это забыл
Re[4]: Вопрос по кодонаписанию
От: Airat Burganov Россия http://www.burganov.com
Дата: 10.01.06 12:41
Оценка:
Здравствуйте, Тычеблин, Вы писали:

Т>спасибо дружище за понимание, а то, получая бессмысленные ответы на вопросы которых я не задавал, я уже начал сомневаться в своей способности объяснять

C тем что написал dshe я согласен, а ни одного ответа на мои вопросы от вас не получил.
Вопросы вы сами не задавали, так что на что отвечать мне — не понятно.

В вашей способности объяснять и понимать я уже не сомневаюсь. Ее просто нет.
Re[5]: Вопрос по кодонаписанию
От: Тычеблин Китай  
Дата: 10.01.06 13:27
Оценка:
Здравствуйте, Airat Burganov, Вы писали:

AB>В вашей способности объяснять и понимать я уже не сомневаюсь. Ее просто нет.


ну так мы не волшебники, мы только учимся....
Re[5]: Вопрос по кодонаписанию
От: Lucker Беларусь http://lucker.intervelopers.com/
Дата: 10.01.06 13:51
Оценка:
Здравствуйте, dshe, Вы писали:

D>К сожалению, EventListenerList не освобождает от необходимости переписывать каждый раз

D>
D> protected void fireFooXXX() {
D>     // Guaranteed to return a non-null array
D>     Object[] listeners = listenerList.getListenerList();
D>     // Process the listeners last to first, notifying
D>     // those that are interested in this event
D>     for (int i = listeners.length-2; i>=0; i-=2) {
D>         if (listeners[i]==FooListener.class) {
D>             // Lazily create the event:
D>             if (fooEvent == null)
D>                 fooEvent = new FooEvent(this);
D>             ((FooListener)listeners[i+1]).fooXXX(fooEvent);
D>         }
D>     }
D> }
D>


Ну так это необходимо для внесения оптимизаций в цикл малтикаста события. Не уверен что эта оптимизация очень сильно влияет на производительность, но небольшой выйгрыш давать должна, иначе ее бы тут не было. В твоем случае необходимо предусматривать каллбак интерфейс для взаимодействия мальтикастера с контекстом его вызова. К сожалению в java нет гибких и простых способов передачи контекста в вызываемый метод.
#333355130
Re[6]: Вопрос по кодонаписанию
От: C0s Россия  
Дата: 10.01.06 14:23
Оценка:
Здравствуйте, Lucker, Вы писали:

L>К сожалению в java нет гибких и простых способов передачи контекста в вызываемый метод.


может я и вырываю из контекста фразу, но мне кажется, что гибкие способы передать контекст в вызываемый метод существуют, а простота/сложность тех трех-четырех известных мне — понятие уже исключительно субъективное, зависящее от привычки, знания языка и непосредственно решаемой задачи

D>>К сожалению, EventListenerList не освобождает от необходимости переписывать каждый раз
protected void fireFooXXX()


L>Ну так это необходимо для внесения оптимизаций в цикл малтикаста события. Не уверен что эта оптимизация очень сильно влияет на производительность, но небольшой выйгрыш давать должна, иначе ее бы тут не было


что касается кода, то субъективно мне он не нравится, прежде всего, сама идея по-разному организовывать циклический перебор
в том смысле, что массив, как мне кажется, из вызова getListenerList() уже должен приходить отфильтрованный массив

ps. а если уж полной придираться, то я бы назвал метод getListeners(), т.к. предпочитаю избегать тавтологий в названиях, а в данном случае видим еще и то, что метод с суффиксом List на самом деле возвращает Array, но это уже все offtopic
Re[7]: Вопрос по кодонаписанию
От: Lucker Беларусь http://lucker.intervelopers.com/
Дата: 10.01.06 14:42
Оценка:
Здравствуйте, C0s, Вы писали:

L>>К сожалению в java нет гибких и простых способов передачи контекста в вызываемый метод.


C0s>может я и вырываю из контекста фразу, но мне кажется, что гибкие способы передать контекст в вызываемый метод существуют, а простота/сложность тех трех-четырех известных мне — понятие уже исключительно субъективное, зависящее от привычки, знания языка и непосредственно решаемой задачи


Да ладно . Нету в java одновременно гибкие и в то же время простого способа передачи контекста (в данном случае нужно иметь возможность этот контекст модифицировать).

C0s>что касается кода, то субъективно мне он не нравится, прежде всего, сама идея по-разному организовывать циклический перебор

C0s>в том смысле, что массив, как мне кажется, из вызова getListenerList() уже должен приходить отфильтрованный массив
C0s>ps. а если уж полной придираться, то я бы назвал метод getListeners(), т.к. предпочитаю избегать тавтологий в названиях, а в данном случае видим еще и то, что метод с суффиксом List на самом деле возвращает Array, но это уже все offtopic

есть еще public EventListener[] getListeners(Class t), но его вероятно не используют все с той же целью оптимизации, дабы не создавать новый массив при каждом чихе.
#333355130
Re[2]: Вопрос по кодонаписанию
От: Тычеблин Китай  
Дата: 10.01.06 14:43
Оценка:
Здравствуйте, dshe, Вы писали:

вот тут Андрей Вишневкий построил фрэймворк там ваще очень интересные идеи


Lightweight events concept

This is a very important chapter. The LwVCL library uses listener concept like Java AWT or SWING libraries. It means that if you want to handle any event you should register an appropriate event listener. The events and listeners are much like in AWT library (see package org.zaval.lw.event.*) and hope, you'll get it easily. But there are several key differences:

First of all, lightweight components don't provide listener support. The lightweight component doesn't implement event distribution functionality and this is really good, because event distribution is concentrated in one place — event manager. This way has one more advantage: it decreases memory usage because lightweight components should not contain the list of listeners (listeners support). It's very simple: if you want to catch events inside your lightweight component, it is necessary just to implement an appropriate listener interface and the library event manager will immediately start sending the events to the component. For example, to catch mouse events inside your component, you should implement LwMouseListener listener interface. As it was described above, a lightweight component doesn't provide listeners support for mouse, key, component, container, focus and other events unlike a Java AWT component. But it is possible to handle all these events using LwEventManager event manager, by registering an appropriate listener. In this case the registered listener will get the events for all components, so if you want to listen the events for the certain lightweight component you should test a source of the events.

The lightweight library provides the mechanism to control input child events. The input event is an event that is initiated by mouse, keyboard or any other input device. This is very important to have this feature for creating composite components. Composite component is a container that consists of several components (child components) that have to work together. For example the LwButton component is a composite component. The button component can have other components (including composite components) as its child. The problem, in this case, is following: if a mouse button has been clicked over any child component, the button mouse listener will not get the mouse event and so cannot handle it. There are several ways to resolve the problem:

Register a mouse listener in by the event manager and test if the source object is the button component or its child component. This solution is like Java AWT (but in this case it is necessary to test if the event source of the event is the child of the composite component), but this way doesn't solve the problem if you want to use other composite component as the button container child component (you cannot control a composite child component).

Control child components' events. The Java AWT hasn't anything like that. The main idea is the parent component can control input events distributing process for its child components. In this case the parent should implement the LwComposite interface and starting from the moment the event manager will "ask" the composite component if the child component input event should be re-directed to the parent. If the composite component says to redirect the input event, the lightweight event manager distributes the event as if the child component doesn't exist. The child becomes "transparent" for the input event. The image below illustrates the composite components concept:


те отлавливать все основные события можно на любом объекте

прикольно то, что это все действительно работает. даже при весьма ограниченных рессурсах и никаких тебе addXXXEvent и проч на самом объекте.
все сосредоточенно в LwEventManager который присутствует в одном экземпляре !!!

круто знай наших
Re[8]: Вопрос по кодонаписанию
От: Airat Burganov Россия http://www.burganov.com
Дата: 10.01.06 14:56
Оценка:
L>есть еще public EventListener[] getListeners(Class t), но его вероятно не используют все с той же целью оптимизации, дабы не создавать новый массив при каждом чихе.
я его использую. Все-таки мои компоненты будут использовать не миллионы программистов по всему миру.
Re[9]: Вопрос по кодонаписанию
От: Lucker Беларусь http://lucker.intervelopers.com/
Дата: 10.01.06 15:02
Оценка:
Здравствуйте, Airat Burganov, Вы писали:

L>>есть еще public EventListener[] getListeners(Class t), но его вероятно не используют все с той же целью оптимизации, дабы не создавать новый массив при каждом чихе.

AB>я его использую. Все-таки мои компоненты будут использовать не миллионы программистов по всему миру.

я имел ввиду компоненты Swing.
#333355130
Re[3]: Вопрос по кодонаписанию
От: dshe  
Дата: 10.01.06 15:27
Оценка:
Здравствуйте, Тычеблин, Вы писали:

Т>Здравствуйте, dshe, Вы писали:


Т> вот тут Андрей Вишневкий построил фрэймворк там ваще очень интересные идеи


Т>прикольно то, что это все действительно работает. даже при весьма ограниченных рессурсах и никаких тебе addXXXEvent и проч на самом объекте.

Т>все сосредоточенно в LwEventManager который присутствует в одном экземпляре !!!

Т>круто знай наших


Вообще-то, что касается работы Андрея Вишневского, то я к нему отношусь пока скептически. Мне показалось, что это Yet Another (GUI) Framework (который к тому же дублирует функциональность Swing/AWT). Многие framework'и обладают одним существенным недостатком -- они intrusive, т.е. как только на какой-то подсядешь, слезть с него будет очень болезненно. Поэтому для того, чтобы какой-то framework использовать, гениальной идеи и великолепной реализации мало, необходима еще уверенность, что завтра этот проект не станет заброшенным и будет все еще конкурентноспособным.
--
Дмитро
Re[10]: Вопрос по кодонаписанию
От: Airat Burganov Россия http://www.burganov.com
Дата: 10.01.06 15:27
Оценка:
AB>>я его использую. Все-таки мои компоненты будут использовать не миллионы программистов по всему миру.
L>я имел ввиду компоненты Swing.
в смысле разработчиков swing'а? Им-то как раз производительность важна, потому что неизвестно где и в каких условиях будут использоваться компоненты миллионами разработчиков
Re[11]: Вопрос по кодонаписанию
От: Lucker Беларусь http://lucker.intervelopers.com/
Дата: 10.01.06 15:41
Оценка:
Здравствуйте, Airat Burganov, Вы писали:

AB>>>я его использую. Все-таки мои компоненты будут использовать не миллионы программистов по всему миру.

L>>я имел ввиду компоненты Swing.
AB>в смысле разработчиков swing'а? Им-то как раз производительность важна, потому что неизвестно где и в каких условиях будут использоваться компоненты миллионами разработчиков

без обид, но сдается мне Тычеблин прав, насчет недопонимания. Я же и имел ввиду что в компонентах Swing-а getListegers() не используется в контексте мултикаст-цикла по причинам оптимизации, дабы не создавать лишние массивы при каждом чихе.
#333355130
Re[4]: Вопрос по кодонаписанию
От: Тычеблин Китай  
Дата: 10.01.06 15:44
Оценка:
Здравствуйте, dshe, Вы писали:

D>Здравствуйте, Тычеблин, Вы писали:


Т>>Здравствуйте, dshe, Вы писали:


Т>> вот тут Андрей Вишневкий построил фрэймворк там ваще очень интересные идеи


Т>>прикольно то, что это все действительно работает. даже при весьма ограниченных рессурсах и никаких тебе addXXXEvent и проч на самом объекте.

Т>>все сосредоточенно в LwEventManager который присутствует в одном экземпляре !!!

Т>>круто знай наших


D>Вообще-то, что касается работы Андрея Вишневского, то я к нему отношусь пока скептически. Мне показалось, что это Yet Another (GUI) Framework (который к тому же дублирует функциональность Swing/AWT). Многие framework'и обладают одним существенным недостатком -- они intrusive, т.е. как только на какой-то подсядешь, слезть с него будет очень болезненно. Поэтому для того, чтобы какой-то framework использовать, гениальной идеи и великолепной реализации мало, необходима еще уверенность, что завтра этот проект не станет заброшенным и будет все еще конкурентноспособным.


было бы интереснее все же про упомянутую идею услышать.


<откровенный оффтоп>

да и навязчивости (интрузивности) особой откровенно я не увидел.
есть возможность совместного (смешанного) использования , немного swing чуть awt и VCL.
конечно многие решения откровенно сомнительны, но на меня произвело впечатление факт того как легко созданное
перекладывается на другие платформы со свингом так не прокатит, точнее прокатит но проще переписать заново.

</откровенный оффтоп>
Re[12]: Вопрос по кодонаписанию
От: Airat Burganov Россия http://www.burganov.com
Дата: 10.01.06 15:52
Оценка:
L>без обид, но сдается мне Тычеблин прав, насчет недопонимания. Я же и имел ввиду что в компонентах Swing-а getListegers() не используется в контексте мултикаст-цикла по причинам оптимизации, дабы не создавать лишние массивы при каждом чихе.
Если кто не использует, сам себе злобный буратино. Создание объектов в java довольно дешевое.
Когда я работал со свингом — использовал, вместо того, чтобы писать ту неудобную процедуру.

конечно, это не относится к непосредственно коду swing'а, там соображения оптимизиации имеют смысл.
Re[8]: Вопрос по кодонаписанию
От: C0s Россия  
Дата: 10.01.06 15:55
Оценка:
Здравствуйте, Lucker, Вы писали:

L>Да ладно . Нету в java одновременно гибкие и в то же время простого способа передачи контекста (в данном случае нужно иметь возможность этот контекст модифицировать).


наверное, мне надо бы спросить, что значит "надо модифицировать"? если контекст суть объект, то этот объект вполне может быть mutable
да и вообще, это вопрос в большей степени философский, ибо когда есть N гибких способов решить какую-то проблему, и ты сумел для себя их них выбрать M и научиться применять, то эти M уже для тебя — простые

L>есть еще public EventListener[] getListeners(Class t), но его вероятно не используют все с той же целью оптимизации, дабы не создавать новый массив при каждом чихе.


если набор листенеров меняется в процессе жизни объекта, то массивы все равно пересоздавать, а если нет — то оптимизация должна быть имхо другой
в любом случае мне не понятно, почему массив в два раза больше по размеру, если язык и так предоставляет информацию о типе

впрочем, мне далекому от мира проблем событийных gui, вообще не понятно, отчего столько мучений... с одной стороны все есть, в т.ч. вложена реализация, которая подстраивается под количество листенеров (если ни одного, то null, если больше одного, то превращается в мультикаст), а с другой стороны интерфейс управления списком подписчиков запихали в предок.

последний раз я программировал gui N-большое лет назад и на delphi, но все равно помню, что для типичной формы или набора форм граф источников-подписчиков в большинстве случаев статичен. если даже требуется замысловатое поведение в динамике а-ля показать текстовое поле ввода, если двумя строками выше выбран радио-баттон такой-то, то предпочтительнее в реализациях листенеров проверять состояние формы (при необходимости можно даже в своей модели завести доп. флаги, нежели проверять видно-не видно), чем на лету перестраивать набор листенеров.
как следствие, можно задачу построения этого графа явно вынести из Component (суть создание объекта посредника) и все нюансы типа выбор между unicast/multicast отдать программисту, вплоть до написания собственных посредников между генераторами событий (Component) и подписчиками — для оптимизаций/наворотов. набор классов наиболее общеупотребимых посредников можно было бы предоставить в подпакете...

или я заблуждаюсь, а создатели Component сэкономили своим копи-пастом программистам много времени?

что касается "so-called оптимизаций", то в глаза бросилось огромное количество приведений типов в AWTEventMulticaster, это, конечно, не массивы создавать по чиху, но все равно не впечатляет
Re[9]: Вопрос по кодонаписанию
От: Lucker Беларусь http://lucker.intervelopers.com/
Дата: 10.01.06 16:16
Оценка:
Здравствуйте, C0s, Вы писали:

C0s>наверное, мне надо бы спросить, что значит "надо модифицировать"? если контекст суть объект, то этот объект вполне может быть mutable

на примере того же цикла: объект Event создается во время работы цикла, если есть хоть один подписчик на собьытие, причем как его создать известно только в контексте fireXXX метода, и переложить эту обязанность на предполагаемую реализацию мультикастера, без создания дополнительных абстракций, невозможно. Иначе проще создать объект Event и передать его в гипотетический мультикастер. Конечно можно проверить, если ли кто из подписчиков на нужное событи в этом самом мультикастере, что опять приведет к повторному кодированию проверки в каждом месте вызова (немного меньше — но все же). Итого, как всегда, или copy-paste, или потери в производительности на дополнительное создание объектов. Я бы выбрал второе, но сантехники должны быбрать первое, так как производительноть свинга — еще та мазоль. Есть третий вариант — правильный — Аспекты, но в силу многих причин современной реализации АОП в java его пока на уровне SDK не применяют. Вероятно со временем все изменится.

Так вот, единственный гибкий и простой способ передачи модифицируемого контекста в вызов — Map или его адаптер, иначе для каждого конктретного случая придется определять свой класс, что вырисовывается в сомнительного преимущества альтернативу. В случае с мапом — проблема с обобщенностью интерфейса и потерей информации о типах на этапе компиляции.

C0s>да и вообще, это вопрос в большей степени философский, ибо когда есть N гибких способов решить какую-то проблему, и ты сумел для себя их них выбрать M и научиться применять, то эти M уже для тебя — простые


Вообще я клоню к тому, что не плохо было бы поиметь closures в java.

C0s>что касается "so-called оптимизаций", то в глаза бросилось огромное количество приведений типов в AWTEventMulticaster, это, конечно, не массивы создавать по чиху, но все равно не впечатляет


не мне тебе рассказыать об истории развития платформы и к чему эта история порой приводит.
#333355130
Re: Вопрос по кодонаписанию
От: tavr  
Дата: 10.01.06 16:51
Оценка:
Здравствуйте, Тычеблин, Вы писали:

Т>Сначала думал оформить в контексте Вопрос по правильному кодонаписанию
Автор: leska
Дата: 06.01.06
потом передумал. У меня вопрос тоже по стилю но о другом.


Т>Предлагаю обсудить то, как можно было бы более правильно и красиво реализовать подписку на собылия объекта и отказ от них.

Т>то как это сделано в AWT/SWING например у Component
Т>лично я нахожу откровенно корявым и загаживающим API. (нет? )

Т>более элегантным решением могло бы стать что-то вроди

Т>таким образом использование будет выглядить так
Т>Но (!) как это может быть устроено внутри? что думаете?

мне в этом смысле нравится идея из SWT:
   addListener(int type, IListener l);
   removeListener(int type, IListener l);
   getListeners(int type);
   fireEvent(int type, Event event);


можно навесить один и тот же listener на несколько типов событий
   addListener(type1 | type2 | type3, IListener l)


легко добавить свои типы событий, определив дополнительную константу
Re[2]: Вопрос по кодонаписанию
От: dshe  
Дата: 10.01.06 17:26
Оценка:
Здравствуйте, tavr, Вы писали:

T>Здравствуйте, Тычеблин, Вы писали:


T>мне в этом смысле нравится идея из SWT:

T>
T>   addListener(int type, IListener l);
T>   removeListener(int type, IListener l);
T>   getListeners(int type);
T>   fireEvent(int type, Event event);
T>


T>можно навесить один и тот же listener на несколько типов событий

T>
T>   addListener(type1 | type2 | type3, IListener l)
T>


T>легко добавить свои типы событий, определив дополнительную константу


А что делать, когда констант не хватит? И как контролировать то, что одна и те же константа не используется для разных целей?
--
Дмитро
Re[13]: Вопрос по кодонаписанию
От: Тычеблин Китай  
Дата: 11.01.06 08:51
Оценка:
Здравствуйте, Airat Burganov, Вы писали:

AB>... Создание объектов в java довольно дешевое.


это утверждение ложно и по памяти и по рессурсам CPU даже для такого банального класса как Object, не говоря про создание экземпляров более сложных классов.
это написано не только в продвинутых трудах по оптимизации, но и в букварях по JAVA.
Re[14]: Вопрос по кодонаписанию
От: Airat Burganov Россия http://www.burganov.com
Дата: 11.01.06 09:42
Оценка:
AB>>... Создание объектов в java довольно дешевое.

Т>это утверждение ложно и по памяти и по рессурсам CPU даже для такого банального класса как Object, не говоря про создание экземпляров более сложных классов.

Т>это написано не только в продвинутых трудах по оптимизации, но и в букварях по JAVA.
ссылки плиз.
Re[14]: Вопрос по кодонаписанию
От: Денис Цыплаков Россия  
Дата: 11.01.06 11:04
Оценка:
Тычеблин пишет:

> это утверждение ложно и по памяти и по рессурсам CPU даже для такого

> банального класса как Object, не говоря про создание экземпляров более
> сложных классов.
> это написано не только в продвинутых трудах по оптимизации, но и в
> букварях по JAVA.

Значит тестируем

IObjectFactory.java
-------------------

package ru.rtec.test.co;

/**
  * Интерфейс фабрики объектов.
  *
  * <p><b>Author</b> : Denis Tsyplakov <b> Date</b>: 11.01.2006 13:46:50</p>
  */
public interface IObjectFactory
{
     Object getObject();
}

----------------------
BeanFactory.java
----------------------

package ru.rtec.test.co;

/**
  * Фабрика бинов
  *
  * <p><b>Author</b> : Denis Tsyplakov <b> Date</b>: 11.01.2006 13:58:18</p>
  */
public class BeanFactory implements IObjectFactory
{

     public Object getObject()
     {
         return new CustomBean();
     }

     class CustomBean
     {
         int i;

         long j;

         boolean b;
     }

}

-------------------------
StringFactory.java
-------------------------

package ru.rtec.test.co;

/**
  * Фабрика строк 0,1,2,3,...
  *
  * <p><b>Author</b> : Denis Tsyplakov <b> Date</b>: 11.01.2006 13:52:09</p>
  */
public class StringFactory implements IObjectFactory
{
     long counter = 0;

     public synchronized Object getObject()
     {
         return new String (""+counter++);
     }
}

------------------------
Tester.java
------------------------

package ru.rtec.test.co;

public class Tester
{

     private static final int TEST_LEHGTH = 100000;

     static Object[] objs = new Object[TEST_LEHGTH];

     public static void main(String[] args)
     {
         System.out.println("кол-во создаваемых объектов: " +
            TEST_LEHGTH);
         test("String Factory",(IObjectFactory)new StringFactory());
         test("Custom bean Factory",(IObjectFactory)new BeanFactory());
     }

     private static void test(final String name,
                              final IObjectFactory factory)
     {
         long start = System.currentTimeMillis();
         for ( int i = 0;i<TEST_LEHGTH;i++)
         {
             objs[i] = factory.getObject();
         }
         long len = System.currentTimeMillis() - start;
         System.out.println(name + " : " + len + " ms.");
     }
}

------------------------
Результаты на CPU 2 ГГц RAM 1Гб
------------------------
кол-во создаваемых объектов: 100000
String Factory : 219 ms.
Custom bean Factory : 63 ms.

Меня такая скорость устраивает.

--
WBR Денис Цыплаков /* jabber UID: denis.tsyplakov@jabber.ru */
Знающий не говорит, говорящий не знает
Posted via RSDN NNTP Server 2.0

Автору поста в подарок от модератора подсветка синтаксиса. Blazkowicz.
Re[15]: Вопрос по кодонаписанию
От: Тычеблин Китай  
Дата: 11.01.06 11:37
Оценка:
Здравствуйте, Airat Burganov, Вы писали:

AB>>>... Создание объектов в java довольно дешевое.


Т>>это утверждение ложно и по памяти и по рессурсам CPU даже для такого банального класса как Object, не говоря про создание экземпляров более сложных классов.

Т>>это написано не только в продвинутых трудах по оптимизации, но и в букварях по JAVA.
AB>ссылки плиз.

мне кажется Вы умышленно недооцениваете свои возможности

http://www.google.ru/search?hl=ru&amp;q=object+creation+cost+java&amp;lr=

первое, что попалось (если уж совсем лениво пользоваться поисковой службой)

здесь
здесь
Re[16]: Вопрос по кодонаписанию
От: Lucker Беларусь http://lucker.intervelopers.com/
Дата: 11.01.06 11:44
Оценка:
Здравствуйте, Тычеблин, Вы писали:

Т>мне кажется Вы умышленно недооцениваете свои возможности


Т>http://www.google.ru/search?hl=ru&amp;q=object+creation+cost+java&amp;lr=


Т>первое, что попалось (если уж совсем лениво пользоваться поисковой службой)


Т>здесь

Т>здесь

ну эти то статьи уже не аргументы, длаго на дваре 2006 (против 2000 в там) и в прадакшене Java SE 5.0, против 1.2.2 d тут. Так что не актуально.
А по существу — опять все зависит от существа. Если у меня веб-приложение, интерфейс к БД или подобное тому — я забью на все эти оптимизации и буду созавать столько объетов, сколько мне надо. Дешевле потом будет добавить один хост в кластер. Если у меня приложение с высокой нагрузкой, у которого просят данные со скоростью до 100 запрсов в секунду — то тут будет важен каждый вновь созданный объект.
#333355130
Re[3]: Вопрос по кодонаписанию
От: tavr  
Дата: 11.01.06 12:26
Оценка:
Здравствуйте, dshe, Вы писали:

D>А что делать, когда констант не хватит?

попросить Sun переписать java

D>И как контролировать то, что одна и те же константа не используется для разных целей?

не совсем понял как ты еще намереваешься использовать типы событий? петь псалмы по ним?
Re[4]: Вопрос по кодонаписанию
От: dshe  
Дата: 11.01.06 13:16
Оценка:
Здравствуйте, tavr, Вы писали:

T>Здравствуйте, dshe, Вы писали:


D>>А что делать, когда констант не хватит?

T>попросить Sun переписать java

D>>И как контролировать то, что одна и те же константа не используется для разных целей?

T>не совсем понял как ты еще намереваешься использовать типы событий? петь псалмы по ним?

Пример: Один разработчик для какого-то своего типа события FOO зарезервировал константу (1<<8), и другой разработчик, ничего не зная о первом, уже для своего события BAR зарезервировал константу (1<<8). В результате этого получается, что одновременно использовать события FOO и BAR невозможно из-за коллизии констант. Мой вопрос был о том, как избежать подобной ситуации?
--
Дмитро
Re[16]: Вопрос по кодонаписанию
От: C0s Россия  
Дата: 11.01.06 13:50
Оценка:
Здравствуйте, Тычеблин, Вы писали:

AB>>>>... Создание объектов в java довольно дешевое.


Т>>>это утверждение ложно и по памяти и по рессурсам CPU даже для такого банального класса как Object, не говоря про создание экземпляров более сложных классов.

Т>>>это написано не только в продвинутых трудах по оптимизации, но и в букварях по JAVA.

Т>дело в том что ситуация с тех далеких пор не сильно-то и изменилась.

Т>и вчера и сегодня и завтра останется верным следущее утверждение
Т>среди всех основных операций, ну там сложение примитивов, обращение к элементу массива.... создание объектов рессурсоемко.

чтобы весь флейм перестал быть голословным надо бы, конечно, найти информацию о конкретных алгоритмах управления памятью в современных JVM

но это сложно, особенно, не будучи сильно в теме. взамен я бы порекомендовал почитать хорошую книгу по разнообразному управлению памятью в C++, там где аллокаторы описываются и перегрузка операций new/delete. естественно, не для того, чтобы стать гуру по C++, а просто чтобы понять, что в основе эффективного управления памятью (создание и удаление объектов) также лежит небольшое количество простых операций.
собственно, ключевой момент в том, что тяжелая и ресурсоемкая часть операции выделения памяти производится не тогда, когда в коде встречается new, а заранее. при new отрабатывает легкий алгоритм поиска подходящего большого блока памяти с последующим инкрементом указателя на его свободную часть (я не имею в виду какую-то конкретную JVM, я намекаю на общий подход), и то и другое — немного арифметики для CPU.
Re[15]: Вопрос по кодонаписанию
От: Blazkowicz Россия  
Дата: 11.01.06 13:57
Оценка:
Здравствуйте, Денис Цыплаков, Вы писали:

ДЦ>------------------------

ДЦ>Результаты на CPU 2 ГГц RAM 1Гб
ДЦ>------------------------
ДЦ>кол-во создаваемых объектов: 100000
ДЦ>String Factory : 219 ms.
ДЦ>Custom bean Factory : 63 ms.

ДЦ>Меня такая скорость устраивает.


ИМХО, основные затраты производительности при создании большого количества временных объектов (коими является массив слушателей определенного типа) уходят на отработку GC, а не на само создание.
Re[16]: Вопрос по кодонаписанию
От: C0s Россия  
Дата: 11.01.06 14:24
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>ИМХО, основные затраты производительности при создании большого количества временных объектов уходят на отработку GC, а не на само создание.


тоже не факт. в том смысле, что GC же не собирает их по одному, а только как-то помечает. после очередного периода анализа все меченые одним махом удаляются (например, изменением статуса их общего блока или инкрементом указателя)

все-таки в контексте создания большого количества объектов имхо самое ресурсоемкое — это их конструкторы, если таковые имеют место быть и делать что-то менее тривиальное, чем пара-тройка переприсваиваний параметров

B>большого количества временных объектов (коими является массив слушателей определенного типа)


и часто такой массив велик? возьмем банальную кнопку, сколько в среднем слушателей ее нажатия?
Re[17]: Вопрос по кодонаписанию
От: Blazkowicz Россия  
Дата: 11.01.06 14:28
Оценка:
Здравствуйте, C0s, Вы писали:

B>>ИМХО, основные затраты производительности при создании большого количества временных объектов уходят на отработку GC, а не на само создание.


C0s>тоже не факт. в том смысле, что GC же не собирает их по одному, а только как-то помечает. после очередного периода анализа все меченые одним махом удаляются (например, изменением статуса их общего блока или инкрементом указателя)

Ну, дык анализ ведь время отниамает а не dispose.

C0s>все-таки в контексте создания большого количества объектов имхо самое ресурсоемкое — это их конструкторы, если таковые имеют место быть и делать что-то менее тривиальное, чем пара-тройка переприсваиваний параметров

Давайте не отвлекатся от темы и обсуждать только наш случай?

B>>большого количества временных объектов (коими является массив слушателей определенного типа)

C0s>и часто такой массив велик? возьмем банальную кнопку, сколько в среднем слушателей ее нажатия?
GC плевать на размер объектов, производительность падает от сложности и размеров дерева объектов.
Re[17]: Вопрос по кодонаписанию
От: Blazkowicz Россия  
Дата: 11.01.06 14:45
Оценка:
Здравствуйте, Денис Цыплаков, Вы писали:

ДЦ> Так вот. GC в современных Ява машинах

ДЦ> 1. Довольно быстрый, плюс есть такая вещь как инкрементальный GC
ДЦ> коорый для многих задач решает проблему на корню.
Согласен.

ДЦ> 2. Многопотоковый. Т.е. когда наступает GC тормозятся не все потоки,

ДЦ> а только тот которому надо памяти, соответсвенно если критичные
ДЦ> нити много пямяти не кушают, а в идеале вообще новых объектов не
ДЦ> создают, то GC их работу не тормозит.
Дык мы тут и имеем новые массивы при каждом обращении к методу. Выходит эти потоки все же будут блокироватся?
Re[18]: Вопрос по кодонаписанию
От: Lucker Беларусь http://lucker.intervelopers.com/
Дата: 11.01.06 14:54
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

ДЦ>> 2. Многопотоковый. Т.е. когда наступает GC тормозятся не все потоки,

ДЦ>> а только тот которому надо памяти, соответсвенно если критичные
ДЦ>> нити много пямяти не кушают, а в идеале вообще новых объектов не
ДЦ>> создают, то GC их работу не тормозит.
B>Дык мы тут и имеем новые массивы при каждом обращении к методу. Выходит эти потоки все же будут блокироватся?

к тому же "эти потоки" — это ивент-диспатчер поток, то есть вероятно появление рывков в интерфесе.
#333355130
Re[19]: Вопрос по кодонаписанию
От: Blazkowicz Россия  
Дата: 11.01.06 14:55
Оценка:
Здравствуйте, Lucker, Вы писали:

B>>Дык мы тут и имеем новые массивы при каждом обращении к методу. Выходит эти потоки все же будут блокироватся?


L>к тому же "эти потоки" — это ивент-диспатчер поток, то есть вероятно появление рывков в интерфесе.


Ну, я это в общем-то и имел в виду.
Re[19]: Вопрос по кодонаписанию
От: Blazkowicz Россия  
Дата: 11.01.06 15:46
Оценка:
Здравствуйте, Денис Цыплаков, Вы писали:

ДЦ> Дело в том, что релаьно сборка мусора может происходить в соседней

ДЦ> нити. А когда придет очередь нашей нити просить памяти — то у VM
ДЦ> уже будет N-цать мегабайт освобожденные пока ждала соседняя нить.

ДЦ> Это конечно как повезет, но в многопотоковой программе, сильно

ДЦ> облегчает жизнь.

В AWT/SWT поток один. Подозреваю что это так во многих других UI системах.

В остальном сдаюсь, leak of performance не может быть вызван именно этими массивами.
Re[19]: Вопрос по кодонаписанию
От: Денис Цыплаков Россия  
Дата: 11.01.06 15:48
Оценка:
Вот в тест в котором выделяются блоки разного размера,
причем не все они сразу удаляются, в каждый второй некоторое
время хранится на куче.

Имитируется фрагментация кучи. Тоже конечно так себе но уже
ближе к реальной жизни. Кол-во итераций и время каждой
итерации уменьшено — поздно домой уже пора идти.
package ru.rtec.test.gc;

import java.util.*;

public class TestGC
{
     static long TEST_LENGTH = 1 * 1000;

     static int blockSize;

     static Queue<byte[]> queue = new LinkedList<byte[]>();

     static int queueSeed = 1;

     public static void main(String[] args)
     {
         for (blockSize = 256; blockSize <= 64 * 1024;
              blockSize = blockSize * 2)
         {
             System.out.println("---\nBlockSize: " + blockSize + " b");
             test();
         }
     }

     private static void test()
     {
         long maxTime = 0;
         long testStart = System.currentTimeMillis();
         long allocCount = 0;
         while (System.currentTimeMillis() - testStart < TEST_LENGTH)
         {
             long startCreate = System.currentTimeMillis();
             byte[] data = new byte[blockSize];
             long cLength = System.currentTimeMillis() - startCreate;
             if (queueSeed % 2 == 1)
             {
                 queue.add(data);
                 if (queue.size() > 20 )
                 {
                     queue.remove();
                 }
             }
             queueSeed++;
             if ( queueSeed > blockSize - 1 )
             {
                 queueSeed = 1;
             }
             if (cLength > maxTime)
             {
                 maxTime = cLength;
             }
             allocCount++;
         }
         System.out.println("Max time: " + maxTime + " ms");
         System.out.println("Allocation count: " + allocCount);
         System.out.println(
                 "Total allocated: " +
                         allocCount * blockSize / 1024 / 1024 + " Mb");
     }

}


Вот результаты. Как видно они не шибко отличаются от предидущего теста.
---
BlockSize: 256 b
Max time: 16 ms
Allocation count: 1640605
Total allocated: 400 Mb
---
BlockSize: 512 b
Max time: 16 ms
Allocation count: 1126191
Total allocated: 549 Mb
---
BlockSize: 1024 b
Max time: 16 ms
Allocation count: 705933
Total allocated: 689 Mb
---
BlockSize: 2048 b
Max time: 16 ms
Allocation count: 386814
Total allocated: 755 Mb
---
BlockSize: 4096 b
Max time: 31 ms
Allocation count: 114607
Total allocated: 447 Mb
---
BlockSize: 8192 b
Max time: 32 ms
Allocation count: 22563
Total allocated: 176 Mb
---
BlockSize: 16384 b
Max time: 47 ms
Allocation count: 5669
Total allocated: 88 Mb
---
BlockSize: 32768 b
Max time: 47 ms
Allocation count: 1906
Total allocated: 59 Mb
---
BlockSize: 65536 b
Max time: 32 ms
Allocation count: 402
Total allocated: 25 Mb



--
WBR Денис Цыплаков /* jabber UID: denis.tsyplakov@jabber.ru */
Знающий не говорит, говорящий не знает
Posted via RSDN NNTP Server 2.0
Re[20]: Вопрос по кодонаписанию
От: Денис Цыплаков Россия  
Дата: 11.01.06 15:51
Оценка:
Blazkowicz пишет:

> В AWT/SWT поток один. Подозреваю что это так во многих других UI системах.


Я знаю. Но в реальной жизни, если разработчик не хочет, чтобы при
каждой блокирующей операции программа серела мордой, то собственно
потоков в программе много. Например у нас принято, что ВСЕ RMI
вызовы — только в отдельном потоке (Callable<ResultType> если
говорить конкретно). Это же касается отчетов и длинных операций с БД

--
WBR Денис Цыплаков /* jabber UID: denis.tsyplakov@jabber.ru */
Знающий не говорит, говорящий не знает
Posted via RSDN NNTP Server 2.0
Re[21]: Вопрос по кодонаписанию
От: Blazkowicz Россия  
Дата: 11.01.06 16:01
Оценка:
Здравствуйте, Денис Цыплаков, Вы писали:

>> В AWT/SWT поток один. Подозреваю что это так во многих других UI системах.


ДЦ> Я знаю. Но в реальной жизни, если разработчик не хочет, чтобы при

ДЦ> каждой блокирующей операции программа серела мордой, то собственно
ДЦ> потоков в программе много. Например у нас принято, что ВСЕ RMI
ДЦ> вызовы — только в отдельном потоке (Callable<ResultType> если
ДЦ> говорить конкретно). Это же касается отчетов и длинных операций с БД

Ну, вот и выходит то же самое что и в Swing, если это наш кастомный проект, то мы об этом можем не заботится особо. Ежели это framework который будет использоватся сторонними лицами, то тут нам и стоит задуматся даже о незначительных оптимизациях производительности.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.