Форум программистов, компьютерный форум, киберфорум
Java
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.59/22: Рейтинг темы: голосов - 22, средняя оценка - 4.59
10 / 10 / 6
Регистрация: 14.03.2011
Сообщений: 392

Начинает медленно работать Java программа

30.09.2013, 14:12. Показов 4805. Ответов 38
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Вот смотрите пишу программу по SMPP. Главный поток выдерает из базы 150смс и начинает их рассылать путем создания ExecutorService. Потом главный поток завершения всех подпотоков, путем вызова get(). Подпотоки отправляют и делают запись в базу.

Так вот. Сначало все нормально СМС идут как положено по 100-150 в секунду, НО вот через некоторое время программа перестает их отправлять с такой скоростью и шлет по 1-2смс/с

Уважаемые форумчане подскажите из за чего такое может случаться ?

Массив в который результаты подпотоков складываю, очищаю в конце ожидания завершения подпотоков
Подпотоки Runnable
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
30.09.2013, 14:12
Ответы с готовыми решениями:

Компьютер начинает медленно работать в игре.
Созрел вопрос. На днях заметил, что когда я играю в одну компьютерную игрушку (Empire total war) стал тупить комп (дёргаться изображение то...

Программа начинает неправильно работать после открытия её в Delphi XE8
Подскажите пожалуйста, почему программа созданная в Borland Delphi 7, которая работает правильно после открытия её в Delphi XE8 начинает не...

Win2000 Advanced Server: при загрузке начинает вешаться, медленно работает
Стоит Win2000 Advanced Server. Симптом: при загрузке начинает вешаться, медленно работает, на нажития мышек/кнопок реагирует с одно-,...

38
ɐwʎ ɔ vǝmоɔ dиw ɐʚонɔ
 Аватар для tankomaz
443 / 442 / 100
Регистрация: 14.10.2012
Сообщений: 1,146
Записей в блоге: 9
30.09.2013, 14:59
где-то "ищет" долго, либо синхронизированный метод мешает. В "чём" храните список, с которого потоки дергают значения куда слать?
0
10 / 10 / 6
Регистрация: 14.03.2011
Сообщений: 392
30.09.2013, 17:09  [ТС]
Вот поток который непосредственно рассылает

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
public class SenderThread implements Runnable {
 
    private int j;
    public  String id;
    private byte[][] byteMessagesArray;
    private String sourceMsisdn;
    private String destinationMsisdn;
    private MessageClass messageClass;
    private Alphabet alphabet;
    private ESMClass esmClass;
    private Integer z;
    private String sms_send_id;
    private String idfull;
 
public SenderThread(int j, byte[][] byteMessagesArray, String id, String idfull, String sms_send_id, String sourceMsisdn, String destinationMsisdn,MessageClass messageClass,
            Alphabet alphabet,ESMClass esmClass,Integer z) {
        this.j = j;
        this.id = id;
        this.byteMessagesArray = byteMessagesArray;
        this.sourceMsisdn = sourceMsisdn;
        this.destinationMsisdn = destinationMsisdn;
        this.messageClass = messageClass;
        this.alphabet = alphabet; 
        this.esmClass = esmClass;
        this.z = z;
        this.sms_send_id=sms_send_id;
        this.idfull=idfull;
    }
private String submitMessageLong(SMPPSession session, byte[] message,String sourceMsisdn, String destinationMsisdn,MessageClass messageClass, Alphabet alphabet, ESMClass esmClass, Integer z) {
        String messageId = null;
        try { //Alphanumeric,ISDN,,INTERNATIONAL,ISDN
            messageId = session.submitShortMessage("", TypeOfNumber.ALPHANUMERIC, NumberingPlanIndicator.ISDN, sourceMsisdn,TypeOfNumber.INTERNATIONAL, NumberingPlanIndicator.ISDN, destinationMsisdn, esmClass, (byte) 0, (byte) 1, null, null, new RegisteredDelivery(SMSCDeliveryReceipt.SUCCESS_FAILURE), (byte) 0, DataCoding.newInstance(z), (byte) 0, message);
        } catch (PDUException e) {
            System.err.println("Invalid PDU parameter");
        } catch (ResponseTimeoutException e) {
            System.err.println("Response timeout");
        } catch (InvalidResponseException e) {
            System.err.println("Receive invalid respose");
        } catch (NegativeResponseException e) {
            System.err.println("Receive negative response");
        } catch (IOException e) {
            System.err.println("IO error occur");
        }
        return messageId;
    }
    
@Override
public void run() {
    String messageId;
    try {
        //Получаем messageId
        messageId = submitMessageLong(MainForm.gatewayTX_Devino.getSession(), byteMessagesArray[j], sourceMsisdn, destinationMsisdn, messageClass, alphabet, esmClass, z);
        if(messageId==null){                                                        
            MainForm.ta.append("NULL -"+destinationMsisdn+"\n");
        }else {
            //Инсертим в smpp_stats_long записть с messageID
            MainForm.stmtInsert.setString(1, id);
            MainForm.stmtInsert.setString(2, messageId);
            MainForm.stmtInsert.setString(3, "");
            MainForm.stmtInsert.setString(4, sms_send_id);
            //Апдейтим smpp, что СМС отправилась
            MainForm.stmtUpdate.setString(1, idfull);
            MainForm.stmtInsert.executeUpdate();
            MainForm.stmtUpdate.executeUpdate();
            MainForm.ta.append("Message submitted, message_id is " + messageId +" "+id+"\n");
        }
    } catch (IOException e1) {} 
      catch (SQLException e) { e.printStackTrace();}                                                           
    }
}
Добавлено через 1 минуту
Ну соответсвенно создается пул таких поток, CachedThreadPool

Добавлено через 4 минуты
Вот главный поток, работает таким образом...
Кликните здесь для просмотра всего текста
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
public void run()
    {  
        while(isActive) 
        { 
            try
               {
                //execService = Executors.newCachedThreadPool();
                rs=null;
                String query = "SELECT phone, text, id, sms_send_id, sms_signature FROM smpp WHERE new=0 AND thread_id=0 LIMIT 150";
                stmt3=MainForm.connection.createStatement();
                rs = stmt3.executeQuery(query);
                while (rs.next()) {
                    String destinationMsisdn = rs.getString(1);
                    MessageClass messageClass = MessageClass.CLASS1;
                    String messageBody = rs.getString(2);
                    String ids = rs.getString(3);
                    sms_send_id = rs.getString(4);
                    String sourceMsisdn = rs.getString(5);
                    
                    //long timeout3= System.currentTimeMillis();
                    final Integer z = Coding(messageBody);  //Coding
                   // timeout3 = System.currentTimeMillis() - timeout3;
                   // MainForm.ta.append("Coding: " + timeout3 +"\n" );
                    
                    //long timeout4= System.currentTimeMillis();
                    final Alphabet alphabet=alphabet(messageBody); //Alphabet
                   // timeout4 = System.currentTimeMillis() - timeout4;
                   // MainForm.ta.append("Alphabet: " + timeout4 +"\n");
                    
                    //long timeout5= System.currentTimeMillis();
                    int maximumSingleMessageSize=maximumSingleMessageSize(messageBody); //maximumSingleMessageSize
                   // timeout5 = System.currentTimeMillis() - timeout5;
                   // MainForm.ta.append("maximumSingleMessageSize: " + timeout5 +"\n");
                    
                    //long timeout6= System.currentTimeMillis();
                    int maximumMultipartMessageSegmentSize=maximumMultipartMessageSegmentSize(messageBody); //maximumSingleMessageSize
                    //timeout6 = System.currentTimeMillis() - timeout6;
                    //MainForm.ta.append("maximumMultipartMessageSegmentSize " + timeout6 +"\n");
                    
                    //long timeout7= System.currentTimeMillis();
                    byte[] byteSingleMessage = byteSingleMessage(messageBody); //byteSingleMessage
                    //timeout7 = System.currentTimeMillis() - timeout7;
                    //MainForm.ta.append("byteSingleMessage " + timeout7 +"\n");
                    
                    // check if message needs splitting and set required sending parameters
                    byte[][] byteMessagesArray = null;
                    ESMClass esmClass = null;
                    //long timeout8= System.currentTimeMillis();
                    if (messageBody.length() > maximumSingleMessageSize) {
                        
                        // split message according to the maximum length of a segment
                        byteMessagesArray = splitUnicodeMessage(byteSingleMessage, maximumMultipartMessageSegmentSize);
                        
                        // set UDHI so PDU will decode the header
                        esmClass = new ESMClass(MessageMode.DEFAULT,MessageType.DEFAULT,GSMSpecificFeature.UDHI);
                    } else {
                        byteMessagesArray = new byte[][] { byteSingleMessage };
                        esmClass = new ESMClass();
                    }
                    //timeout8 = System.currentTimeMillis() - timeout8;
                    //MainForm.ta.append("режем смску на части: " + timeout8 +"\n");
                      synchronized(this){
                          while(suspendFlag) {
                               wait();
                               MainForm.ta.append("Thread 1 suspended"+"\n");
                            }
                      }
                        // submit all messages
                        for (int j = 0; j < byteMessagesArray.length; j++) {
                            id="";
                            idfull="";
                            id=ids+'-'+j;
                            idfull=ids;
                            Future future = execService.submit(new SenderThread (j, byteMessagesArray, id, idfull, sms_send_id, sourceMsisdn, destinationMsisdn, messageClass, alphabet, esmClass, z) {});
                            list.add(future);
                       }
 
                      }//end while
                } catch (SQLException e) {
                       StringWriter errors = new StringWriter();
                       e.printStackTrace(new PrintWriter(errors));
                       MainForm.ta.append(errors.toString());
                       MainForm.ConnectToMySQL();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally{
                    try {
                          for (Future<Runnable> f : list)
                          {
                             try {
                                f.get();
                            } catch (InterruptedException | ExecutionException e) {
                                e.printStackTrace();
                            }
                          }
                        list.clear();
                        rs.close();
                        stmt3.close();
                        //execService.shutdown();
                    } catch (SQLException e) {} 
 
                }                   
        }
    }


Добавлено через 11 минут
Что там искать можно , все же чистится после первой итерации, да и синхронизированных методов нет вроде...

Добавлено через 38 минут
Нету никаких идей ? Вроде бы не очень сложный код для восприятия
0
KeM6Pug}I{a
49 / 49 / 1
Регистрация: 23.08.2013
Сообщений: 202
30.09.2013, 18:31
Цитата Сообщение от Critically Посмотреть сообщение
Ну соответсвенно создается пул таких поток, CachedThreadPool
А не жирно вам будет каждое смс в новом потоке отправлять ? Использутей FixedThreadPool

PS наверно из за этого и лагает так как на создавали over9999 потоков , а потом двух ядерному процу переключаться между ними...
1
10 / 10 / 6
Регистрация: 14.03.2011
Сообщений: 392
30.09.2013, 18:53  [ТС]
1) А зачем должно создаваться over99999 потоков, ChachedThreadPool разве потом не берет потоки которые были уже использованы ? В описании вроде так...

2)У меня создание ExecutorService статическое... Но смотрите какой момент. Программа сама делит текст смс тоесть ясли я выбираю 100смс из базы, программа делит их на части, получается допустим 2 части, то 100*2 это 200. Тоесть каждый раз нужно будет пересоздавать динамически Executor и прописывать FixedThreadPool

3) Я уже пробовал допустим создавать динамически Executor но если много раз создавать объект то, Memory Analyzer мне выдавал какую то гадость, ошибку по памяти, лика не было, но программа весила 800мб, теперь я сделал его статическим и программа стала занимать 100мб.

Что посоветуете ?
0
KeM6Pug}I{a
49 / 49 / 1
Регистрация: 23.08.2013
Сообщений: 202
30.09.2013, 19:14
Цитата Сообщение от Critically Посмотреть сообщение
1) А зачем должно создаваться over99999 потоков, ChachedThreadPool разве потом не берет потоки которые были уже использованы ?
ChachedThreadPool создает каждый раз новый поток если нету потоков в кеше , а вы запускаете сразу в него 200+ смсок так вот он вам и создает 200 потоков ( мб 1 поток успеет выполнить сразу 2 таска , но с каждом новым таском это вероятность уменьшается)
1
10 / 10 / 6
Регистрация: 14.03.2011
Сообщений: 392
30.09.2013, 19:21  [ТС]
Цитата Сообщение от MbICJIuTeJIb_u3 Посмотреть сообщение
ChachedThreadPool создает каждый раз новый поток если нету потоков в кеше , а вы запускаете сразу в него 200+ смсок так вот он вам и создает 200 потоков ( мб 1 поток успеет выполнить сразу 2 таска , но с каждом новым таском это вероятность уменьшается)
Вообщем я так понял №2 моего поста выше, это самый оптимальный вариант так ?

Добавлено через 5 минут
Может еще какие то советы дадите, гуру Java будте любезны помогите пожалуйста...
0
KeM6Pug}I{a
49 / 49 / 1
Регистрация: 23.08.2013
Сообщений: 202
30.09.2013, 20:02
Цитата Сообщение от Critically Посмотреть сообщение
Я уже пробовал допустим создавать динамически Executor но если много раз создавать объект
Здесь я не понял , зачем много раз создавать объект ? Один Executor'a хватит на всю программу.
0
10 / 10 / 6
Регистрация: 14.03.2011
Сообщений: 392
30.09.2013, 20:56  [ТС]
Ну ExecutorService exec = new FixedThreadPool(N); У меня N каждый раз разное, и если смс будет больше чем N то прога то будет тормозить...
0
Эксперт Java
 Аватар для turbanoff
4094 / 3828 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 12
30.09.2013, 21:08
У вас много потоков обращаются сразу к одним и тем же Statement-ам и вызывает их? Вы уверены что это нормально? (Я уверен, что это ужасная идея и, возможно, проблема в этом)

PS. Зачем у вас создается анонимный подкласс SenderThread? Уберите фигурные скобки
Future future = execService.submit(new SenderThread (j, byteMessagesArray, id, idfull, sms_send_id, sourceMsisdn, destinationMsisdn, messageClass, alphabet, esmClass, z) {});
Добавлено через 5 минут
И еще: всегда закрывайте объекты СУБД (Connection, ResultSet, Statement) в блоке finally.
1
10 / 10 / 6
Регистрация: 14.03.2011
Сообщений: 392
30.09.2013, 22:00  [ТС]
Цитата Сообщение от turbanoff Посмотреть сообщение
У вас много потоков обращаются сразу к одним и тем же Statement-ам и вызывает их? Вы уверены что это нормально? (Я уверен, что это ужасная идея и, возможно, проблема в этом)

PS. Зачем у вас создается анонимный подкласс SenderThread? Уберите фигурные скобки


Добавлено через 5 минут
И еще: всегда закрывайте объекты СУБД (Connection, ResultSet, Statement) в блоке finally.
1)
Как бы вы предложили решить эту проблему ?

2)
Не заметил скобки, уберу

3)
Я их закрываю
rs.close();
stmt3.close();
Не закрываю только preparedStatement-ы. А коннект зачем закрывать ? Каждый раз потом опять коннектится ?
0
Эксперт Java
 Аватар для turbanoff
4094 / 3828 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 12
30.09.2013, 22:09
1. Варианта два - использовать синхронизацию, либо создавать свой connection/Statement на каждый поток.
Я бы взял какую-нибудь реализацию пула соединения с БД (c3p0, tomcat DBCP, Oracle UCP, ...) и использовал его для создания Connection-ов и использовал в каждом потоке свой Connection.

Добавлено через 3 минуты
3. Что если list.clear() бросит Exception? rs.close() тогда не вызовется.

Что если Exception бросится на строке 10?
Java
10
       stmt3=MainForm.connection.createStatement();
У вас rs.close() вызовет NPE
1
10 / 10 / 6
Регистрация: 14.03.2011
Сообщений: 392
30.09.2013, 22:54  [ТС]
Цитата Сообщение от turbanoff Посмотреть сообщение
1. Варианта два - использовать синхронизацию, либо создавать свой connection/Statement на каждый поток.
Я бы взял какую-нибудь реализацию пула соединения с БД (c3p0, tomcat DBCP, Oracle UCP, ...) и использовал его для создания Connection-ов и использовал в каждом потоке свой Connection.

Добавлено через 3 минуты
3. Что если list.clear() бросит Exception? rs.close() тогда не вызовется.

Что если Exception бросится на строке 10?
Java
10
       stmt3=MainForm.connection.createStatement();
У вас rs.close() вызовет NPE
1. Синхронизацию нельзя, надо асинхронно иначе медленно отправляется смс-ки.

3. Я это знаю просто руки не доходят ) Основной вопрос не в этом.. А в медленной работе программы, через 1 2 итерации потока...

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

Добавлено через 3 минуты
Если вас не затруднит можете рассказать поподробнее чем 1 connection так плох ?
0
Эксперт Java
 Аватар для turbanoff
4094 / 3828 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 12
01.10.2013, 07:15
Цитата Сообщение от Critically Посмотреть сообщение
Если вас не затруднит можете рассказать поподробнее чем 1 connection так плох ?
Тем, что объекты JDBC (Connection, ResultSet, Statement) не thread-safe и работа с ними в разных потоках может привести к печальным последствиям. Каким? Зависит от фазы луны, JVM , ОС и процессора.
Цитата Сообщение от Critically Посмотреть сообщение
Синхронизацию нельзя, надо асинхронно иначе медленно отправляется смс-ки.
Так вы можете, отправлять СМС в разных потоках, а БД обновлять уже потом в одном.
0
10 / 10 / 6
Регистрация: 14.03.2011
Сообщений: 392
01.10.2013, 12:32  [ТС]
Вообщем я тут прикинул. Проблема такова что мне нужно каждый раз рассылать смс асинхронно, но количество потоков в пуле каждый раз может быть разным... Тоесть рассылая допустим 10-смс по 1-ой части то будет 10 потоков, рассылая 10-смс по 2-е части то будет 20 потоков.

Хмм нужно что бы при каждой итерации создавался новый пул потоков с определенным количеством потоков...

Как такое реализовать подскажите пожалуйста.

Пример: Создаем пул на 100 потоков, он отработал, еще создаем пул потоков допустим на 50 потоков, но при этом первый пул то уже не нужен и его надо удалить как то...
0
10 / 10 / 6
Регистрация: 14.03.2011
Сообщений: 392
01.10.2013, 14:11  [ТС]
Вот залогировать решил программу, логи большие но самое интересное в конце начинается... Господа гуру, может быть кто то сталкивался с такой проблемой, все числа в милисекундах, это время выполнения операций. Шлю по 20смс. Пул Cached.

loging.txt

Во во вложении. лог. В конце программа начинает себя очень странно вести и я не могу понять почему так...
0
10 / 10 / 6
Регистрация: 14.03.2011
Сообщений: 392
01.10.2013, 16:13  [ТС]
Ну что есть какие либо идеи ?
0
Эксперт Java
 Аватар для turbanoff
4094 / 3828 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 12
01.10.2013, 17:29
Цитата Сообщение от Critically Посмотреть сообщение
Создаем пул на 100 потоков, он отработал, еще создаем пул потоков допустим на 50 потоков, но при этом первый пул то уже не нужен и его надо удалить как то
Зачем вам тогда пул? Вы описали работу обычного запуска потоков.
0
10 / 10 / 6
Регистрация: 14.03.2011
Сообщений: 392
01.10.2013, 18:43  [ТС]
Думаете без пула, просто попробовать обычных потоков запускать ?

Добавлено через 37 минут
А вы посмотрели логи, что скажете ? Программа то работает просто начинает тормозить и не понятно почему ((
0
 Аватар для mutagen
2587 / 2260 / 257
Регистрация: 14.09.2011
Сообщений: 5,185
Записей в блоге: 18
01.10.2013, 19:46
Цитата Сообщение от Critically Посмотреть сообщение
Ну что есть какие либо идеи ?
если вы пулл не переиспользуете и хотите создавать заново, то зачем он вам вообще нужен
Его создали чтобы уменьшить накладные расходы на создание потока, у вас такой проблемы нет
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
01.10.2013, 19:46
Помогаю со студенческими работами здесь

После переустановки Windows - страница при просмотре спускается очень медленно и начинает плавать
После того как я переустановил windows xp с компьютером что-то странное. Когда я просматриваю страницу в интернете и пытаюсь спуститься...

после установки любого драйвера для видеокарты, монитор начинает мигать, изображения загружаются медленно
Здравствуйте!больше не знаю что делать, подскажите) снес винду, отформатировал жесткий, всё нормально, но после установки любого драйвера...

Какой браузер лучше установить вместо Opera? (после получаса работы начинает медленно открывать вкладки)
Здравствуйте! Посоветуйте пожалуйста, какой лучше браузер на сегодняшней день лучший? Ребят, стоит опера, но после получаса работы начал...

Unity начинает медленно отрисовывать падение персонажа (Как бы проседает FPS, но только на падение)
Собственного говоря, всем здравствуйте! Я в юнити работаю очень редко, но всегда хотелось (как, думаю, и многим) написать собственную...

Поток не начинает работать
Здравствуйте, столкнулся с очень необычной штукой, по крайней мере для меня. Созданные потоки и он просто не начинает работать. Даже не...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это дополнительная запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru