#android #multithreading #out-of-memory #threadgroup
#Android #многопоточность #не хватает памяти #threadgroup
Вопрос:
Я создаю множество экземпляров surface view для просмотра некоторых объектов, но за раз создается один экземпляр, а затем вызывается surfaceDestroyed. но поток, который я создаю каждый раз в surfacecreated, добавляется в основную группу потоков.
Хотя я прерываю и аннулирую его, но он по-прежнему находится в основной группе потоков и создает исключение нехватки памяти.
Фрагменты кода: конструктор
public class MsurfaceView extends SurfaceView implements
SurfaceHolder.Callback {
_thread = new mThread(this);
_thread.setName("mThread");
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (!_thread.isAlive()) {
_thread = new BreedingThread(this);
}
_thread.setRunning(true);
_thread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d("mThread", "Surface Destroyed Called");
getHolder().removeCallback(this);
getHolder().addCallback(null);
boolean retry = true;
_thread.setRunning(false);
while (retry) {
try {
_thread.interrupt();
_thread.getThreadGroup().interrupt();
_thread.join();
retry = false;
} catch (InterruptedException e) {
Log.d("mThread", "Interrupted");
// pass interrupt exception
Thread.currentThread().interrupt();
Log.d("mThread", "b4 threadGroupInterrupted");
_thread.getThreadGroup().interrupt();
_thread.getThreadGroup().list();//this shows thread is in //list
_thread = null;
break;
}
}
}
Обновить
Нитки.функция list показывает, что мой прерванный и нулевой поток все еще находится в threadgroup
06-10 15:22:52.780: INFO/System.out(1814): java.lang.ThreadGroup[name=main,maxPriority=10]
06-10 15:22:52.780: INFO/System.out(1814): Thread[main,5,main]
06-10 15:22:52.780: INFO/System.out(1814): Thread[Thread-2,5,main]
06-10 15:22:52.780: INFO/System.out(1814): Thread[Binder Thread #1,5,main]
06-10 15:22:52.780: INFO/System.out(1814): Thread[Binder Thread #2,5,main]
06-10 15:22:52.780: INFO/System.out(1814): Thread[FlurryAgent,5,main]
06-10 15:22:52.780: INFO/System.out(1814): Thread[AsyncTask #1,5,main]
06-10 15:22:52.780: INFO/System.out(1814): Thread[AsyncTask #2,5,main]
06-10 15:22:52.780: INFO/System.out(1814): Thread[Thread-17,5,main]
06-10 15:22:52.780: INFO/System.out(1814): Thread[mThread,5,main]
06-10 15:22:52.780: INFO/System.out(1814): Thread[mThread,5,main]
06-10 15:22:52.780: INFO/System.out(1814): Thread[mThread,5,main]
06-10 15:22:52.780: INFO/System.out(1814): Thread[Thread-38,5,main]
06-10 15:22:52.780: INFO/System.out(1814): Thread[Timer-2,5,main]
06-10 15:22:52.780: INFO/System.out(1814): Thread[mThread,5,main]
06-10 15:22:52.780: INFO/System.out(1814): Thread[mThread,5,main]
06-10 15:22:52.780: INFO/System.out(1814): Thread[Thread-53,5,main]
06-10 15:22:52.780: INFO/System.out(1814): Thread[Thread-286,5,main]
06-10 15:22:52.780: INFO/System.out(1814): Thread[Thread-327,5,main]
06-10 15:22:52.780: INFO/System.out(1814): Thread[Thread-359,5,main]
06-10 15:22:52.780: INFO/System.out(1814): Thread[mThread,5,main]
06-10 15:22:52.780: INFO/System.out(1814): Thread[Thread-409,5,main]
как их удалить ?
Комментарии:
1. не полный код; просто фрагменты кода для понимания. Я создаю этот surfaceview и этот поток после того, как один из них уничтожен
2. Как я уже говорил в вашем другом потоке. Вам не нужно их удалять, и не следует их удалять. Вместо этого вам следует исправить свой код, чтобы ваши потоки завершались и чтобы вы не ссылались на них.
3. Анализ hProf показывает, что только основная группа потоков ссылается на мой BreedingThread
4. Это означает, что поток все еще выполняется.
5. System.out.println(«isRunning » _thread.isRunning()); ===> false System.out.println(«IsAlive » _thread.IsAlive());==> true
Ответ №1:
На что следует обратить внимание.
- Вы вызываете _thread = null только внутри блока catch — это означает, что для него не будет установлено значение null, если исключение никогда не генерируется. Переместите это в блок finally.
- Это исключение, вероятно, никогда не выдается. Вызов Thread.interrupt() не приведет к его запуску. Это устанавливает флаг прерывания потока в значение true. Весь этот цикл while довольно странный, и вам, вероятно, следует его переписать.
- Вы передаете экземпляр этого в BreedingThread. Убедитесь, что объект не содержит ссылку на ваш surface view навсегда
- Простой вызов метода surface view destroy не означает, что ссылка будет удалена, если что-то все еще содержит ссылку на него (как я упоминал, например, в 3).
Комментарии:
1. в журнале выводится сообщение о том, что поток прерывается. Я использовал hprof с анализатором памяти и показывает только, что breedingThread создает беспорядок из-за переполнения памяти, и все экземпляры surface view были удалены из памяти. Я перевожу _thread=null; в finally. спасибо, пожалуйста, помогите
Ответ №2:
Когда вы вызываете «новый поток» и не указываете группу, поток будет добавлен в ту же группу, что и вызывающий (т.Е. Thread.currentThread().getThreadGroup()
). В вашем случае именно это приводит к добавлению ваших потоков в группу потоков «main». Чтобы изменить это поведение, используйте new Thread(group, this)
для указания группы.