Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

Программирование Android

Войти
Регистрация
Восстановить пароль
 
DarkVortex
103 / 69 / 18
Регистрация: 07.07.2014
Сообщений: 239
#1

Модификатор synchronized и Runnable - Программирование Android

24.01.2016, 22:50. Просмотров 290. Ответов 3
Метки нет (Все метки)

Имеется сервис в котором крутится поток работающий с сетью, проблема в том, что при некоторых(больше месяца пытаюсь понять каких) обстоятельствах создается несколько экземпляров этого сервиса.
Перед запуском проверяю не запущен ли он так:
Java
1
2
3
4
5
6
7
8
9
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> rs = am.getRunningServices(Integer.MAX_VALUE);
boolean run = true;
for (int i = 0; i < rs.size(); i++) {
        ActivityManager.RunningServiceInfo rsi = rs.get(i);
    if(rsi.service.getClassName().contains("MyService")){
        run = false;   
        }
}
Но почему-то на некоторых устройствах сервис все равно запускается повторно(Зависимость в моделях и прошивках не нашел) но проблема возникает на android 4.4+.
Не придумав ничего лучше решил сделать так:
Java
1
2
3
4
5
6
public class MyClient implements Runnable{
    public synchronized void run(){
        //code
        
        }
}
Вручную запустил несколько потоков и как и ожидал все они выполнились последовательно. Выпустил в релиз но проблема не решилась. Некоторые клиенты работают с несколькими потоками, в нормальном случае в приложении не больше 6 потоков, у проблемных устройств их много больше. Физического доступа к ним к сожалению нет, на своих устройствах воспроизвести проблему не удалось.
Использование IntentService не подойдет, т.к. сервис должен стартовать в основном потоке.
Как можно гарантировать запуск только 1 экземпляра сервиса? Что-то у меня совсем не выходит(

Добавлено через 12 минут
Пример лога от проблемного устройства
Bash
1
2
3
4
5
6
7
8
9
10
1453658697.64 : 66 : 46.200.243.230 -> 1: LOGIN:||:356417062239070:||:API1:||:16596:||:26
1453658697.71 : 66 : 356417062239070 <- GET_CONNECTION_TYPE
1453658697.79 : 68 : 46.200.243.230 -> 1: LOGIN:||:356417062239070:||:API1:||:16550:||:26
Close duplicate connection 356417062239070
1453658697.85 : 68 : 356417062239070 <- GET_CONNECTION_TYPE
1453658697.85 : 69 : 46.200.243.230 -> 1: LOGIN:||:356417062239070:||:API1:||:16602:||:26
Close duplicate connection 356417062239070
1453658697.91 : 69 : 356417062239070 <- GET_CONNECTION_TYPE
1453658697.91 : 70 : 46.200.243.230 -> 1: LOGIN:||:356417062239070:||:API1:||:16623:||:26
Close duplicate connection 356417062239070
Предпоследнее значение id потока, последнее количество потоков в процессе, т.е. на модификатор synchronized ему явно плевать. Мне кажется это не очень нормальное поведение.

Добавлено через 56 минут
Теоретически дубликат сервиса может запуститься таким образом: поскольку за жизнью сервиса следит AlarmManager может произойти так, что android грохнет сервис из-за внешних факторов, сработает AlarmManager и запустит его, затем android решит воскресить старый сервис (он же липкий START_STICKY) и вот уже 2 сервиса. Возможно на загруженном кучей приложений устройстве это происходит достаточно часто.
Тогда задача сводится к следующему, как сделать так чтобы работал только 1 поток, попробую сделать из него singleton...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
24.01.2016, 22:50
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Модификатор synchronized и Runnable (Программирование Android):

Потоки (Handler внутри synchronized) - Программирование Android
private Handler Ocnova = new Handler(); private Object sync = new Object(); class newThread extends Thread { //...String mes..... ...

PostDelayed можно ли в Runnable передавать аргумент, как-то так? - Программирование Android
Добрый день, форумчане гуру и прочие знающие люди! Помогите начинающему программеру! Есть метод .postDelayed который замечательно...

Как получить данные из Runnable процесса вызываемого из CallBack функции - Программирование Android
Доброго всем суток, вопрос новичка, учусь.. Пишу программу под Андроид, в главном классе создал метод MethodName в котором всё...

Implements Runnable - Java
Необходимо создать 10 треугольников и реализовать анимацию для них (простое движение сверху вниз). Triangle.java package aectann; ...

Не срабатывет пример с Runnable - Java SE
Написал код по примеру с классом Runnable class Thread2 implements Runnable { String str; Thread2(String str) { this.str = str; }...

synchronized - Java SE
class Data { int count =0; static int countSt =0; } class MyThread implements Runnable { Data obj;

3
YuraAAA
1576 / 1317 / 271
Регистрация: 25.10.2009
Сообщений: 3,438
Записей в блоге: 2
24.01.2016, 23:20 #2
Цитата Сообщение от DarkVortex Посмотреть сообщение
public synchronized void run
Этот synchronized вообще никак не влияет.
Цитата Сообщение от DarkVortex Посмотреть сообщение
несколько экземпляров этого сервиса.
Именно service? Тогда это невозможно
0
DarkVortex
103 / 69 / 18
Регистрация: 07.07.2014
Сообщений: 239
25.01.2016, 12:55  [ТС] #3
Цитата Сообщение от YuraAAA Посмотреть сообщение
Этот synchronized вообще никак не влияет.
Так лучше?
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class SyncThread implements Runnable{
    private static final Object lock = new Object();        
    
    public void run() {
        synchronized(lock) {
            Log.d("TAG", "run() start");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Log.d("TAG", "run() end");
        }
    }
}
Java
1
2
3
4
5
6
        Thread sync_thread = new Thread(new SyncThread());
        sync_thread.start();
        Thread sync_thread2 = new Thread(new SyncThread());
        sync_thread2.start();
        Thread sync_thread3 = new Thread(new SyncThread());
        sync_thread3.start();
Лог:
Bash
1
2
3
4
5
6
D/TAG     (19792): run() start
D/TAG     (19792): run() end
D/TAG     (19792): run() start
D/TAG     (19792): run() end
D/TAG     (19792): run() start
D/TAG     (19792): run() end
Добавлено через 1 час 39 минут
Печаль вся в том, что класс этого потока у меня в отдельном dex лежит и довольно часто в фоне обновляется. Если dex файл перегрузить новый класс этого потока напрочь забудет о синхронизации и о том что его устаревшая копия уже работает он не узнает.

Добавлено через 1 час 36 минут
В итоге сделал вот так:
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
class SyncThread implements Runnable{
    public void run() {
        Set<Thread> all_stack = Thread.getAllStackTraces().keySet();
        for(Thread t : all_stack){
            if(t.getName().contains("SyncThread")){
                t.interrupt();
            }
        }
        Thread ct = Thread.currentThread();
        String tid = String.valueOf(ct.getId());
        ct.setName("SyncThread-" + tid); 
        
        Log.d("TAG", "run() start");
        while(!Thread.interrupted()){
            Log.d("TAG", "run() " + tid + " - " + String.valueOf(ct.getName()));
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                ct.interrupt();
            }
        }
        Log.d("TAG", "run() end");
    }
}
Новый поток тормознет старый, даже если это уже 2 разных класса

Добавлено через 3 минуты
Конечно если их не запускать одновременно, но в моем случае это невозможно
0
YuraAAA
1576 / 1317 / 271
Регистрация: 25.10.2009
Сообщений: 3,438
Записей в блоге: 2
25.01.2016, 12:55 #4
DarkVortex, да запустите Вы их через singleThreadPoolExecutor и всё
1
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
25.01.2016, 12:55
Привет! Вот еще темы с ответами:

Не открывается Runnable JAR File - Java
Экспортирую программу, выбирая Runnable JAR File, когда пробуй открыть файл - ничего не происходит. Пробую делать другую программу (просто...

Ant i runnable jar file - Java SE
вобшем собираю простенький swing'oвий проект, собираю с помощью Eclipse, все собирается через вайзерды(правой кнопкой по проекту export...

Ошибки при добавлении new Runnable - Java SE
executorService.execute(new Runnable() { @Override public void run() { - без этого работала без ошибок,...

Внести переменную в поток runnable - Java SE
for (int j = 0; j &lt; byteMessagesArray.length; j++) { execService.execute (new Runnable () { public void run () { String...


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

Или воспользуйтесь поиском по форуму:
4
Yandex
Объявления
25.01.2016, 12:55
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru