android 차이 - 안드로이드 AsyncTask 스레드 제한?




2 Answers

모든 AsyncTask는 공유 (정적) ThreadPoolExecutorLinkedBlockingQueue 의해 내부적으로 제어됩니다. AsyncTask에서 execute 를 호출하면 ThreadPoolExecutor 는 나중에 일정 시간이 지나면 실행할 수 있습니다.

'언제 내가 준비 됐니?' ThreadPoolExecutor 동작은 코어 풀 크기최대 풀 크기의 두 매개 변수로 제어됩니다. 현재 코어 풀 크기보다 작은 스레드가 현재 활성 상태이고 새 작업이 들어 오면 실행 프로그램은 새 스레드를 작성하고 즉시 실행합니다. 실행중인 코어 풀 크기의 스레드가 적어도 있으면 작업 대기열에 넣고 사용 가능한 유휴 스레드 (즉, 다른 작업이 완료 될 때까지)가 될 때까지 대기합니다. 작업을 대기열에 넣을 수없는 경우 (대기열은 최대 용량을 가질 수 있음) 작업을 실행하기위한 새로운 스레드 (최대 풀 크기 스레드까지)를 작성합니다. 비 핵심 유휴 스레드는 결국 해제 될 수 있습니다 keep-alive timeout 매개 변수에 따릅니다.

Android 1.6 이전에는 코어 풀 크기가 1이고 최대 풀 크기는 10이었습니다. Android 1.6 이후 코어 풀 크기는 5이고 최대 풀 크기는 128입니다. 두 경우 모두 대기열 크기는 10입니다. keep-alive timeout은 2.3 초 전에 10 초 였고 그 이후로 1 초가되었습니다.

이 모든 것을 염두에두고 AsyncTask 가 5/6의 작업 만 실행하는 것처럼 보이는 이유는 이제 분명해진다. 6 번째 작업은 다른 작업 중 하나가 완료 될 때까지 대기열에 있습니다. 이것은 장기 실행 작업에 AsyncTasks를 사용하지 않아야하는 매우 좋은 이유입니다. 다른 AsyncTask가 실행되는 것을 방지합니다.

완전성을 위해 6 개 이상의 작업 (예 : 30 개)으로 연습을 반복하면 대기열이 가득 차고 실행자가 밀어 넣어 더 많은 작업자 스레드를 만들 때 6 개 이상이 doInBackground 들어갑니다. 장기 실행 작업을 계속 수행했다면 20/30이 활성 상태가되고 대기열에 10이 계속 남아 있어야합니다.

thread handlerthread

나는 사용자가 시스템에 로그인 할 때마다 일부 정보를 업데이트해야하는 응용 프로그램을 개발 중이며 전화에서 데이터베이스도 사용합니다. 모든 작업 (업데이트, db에서 데이터 검색 등)에는 비동기 작업을 사용합니다. 지금까지는 왜 내가 사용하지 말아야하는지 알지 못했지만 최근에는 일부 작업을 수행 할 때 비동기 작업 중 일부가 실행 전 중지되고 doInBackground로 점프하지 않는다는 것을 경험했습니다. 그것은 그렇게 이상하게 남겨 두었습니다. 그래서 나는 무엇이 잘못되었는지 확인하기 위해 또 다른 간단한 응용 프로그램을 개발했습니다. 그리고 이상하게도 전체 비동기 작업의 수가 5에 도달하면 동일한 동작을 얻습니다. 6 번째 작업은 사전 실행시 중지됩니다.

안드로이드는 액티비티 / 앱에서 asyncTasks의 한도를 갖고 있습니까? 아니면 단지 버그 일 뿐이며보고해야합니까? 다른 사람이 같은 문제를 경험했거나 해결 방법을 찾을 수 있었습니까?

다음은 코드입니다.

백그라운드에서 작동하는 스레드 5 개를 작성하기 만하면됩니다.

private class LongAsync extends AsyncTask<String, Void, String>
{
    @Override
    protected void onPreExecute()
    {
        Log.d("TestBug","onPreExecute");
        isRunning = true;
    }

    @Override
    protected String doInBackground(String... params)
    {
        Log.d("TestBug","doInBackground");
        while (isRunning)
        {

        }
        return null;
    }

    @Override
    protected void onPostExecute(String result)
    {
        Log.d("TestBug","onPostExecute");
    }
}

그런 다음이 스레드를 만듭니다. 그것은 preExecute로 들어가서 멈출 것이다 (doInBackground에는 가지 않을 것이다).

private class TestBug extends AsyncTask<String, Void, String>
{
    @Override
    protected void onPreExecute()
    {
        Log.d("TestBug","onPreExecute");

        waiting = new ProgressDialog(TestActivity.this);
        waiting.setMessage("Loading data");
        waiting.setIndeterminate(true);
        waiting.setCancelable(true);
        waiting.show();
    }

    @Override
    protected String doInBackground(String... params)
    {
        Log.d("TestBug","doInBackground");
        return null;
    }

    @Override
    protected void onPostExecute(String result)
    {
        waiting.cancel();
        Log.d("TestBug","onPostExecute");
    }
}



업데이트 : API 19 이후, 최대 스레드 풀 크기는 장치의 CPU 수를 반영하도록 변경되었습니다. 시작시 최소 2와 최대 4, 최대 CPU * 2로 증가하면서 +1

// We want at least 2 threads and at most 4 threads in the core pool,
// preferring to have 1 less than the CPU count to avoid saturating
// the CPU with background work
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;

또한 AsyncTask의 기본 실행 프로그램은 직렬 (한 번에 하나의 작업을 순서대로 실행 함)이며 method

public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
        Params... params)

Executor를 제공하여 작업을 실행할 수 있습니다. 후드 실행자 아래에 THREAD_POOL_EXECUTOR를 제공 할 수도 있지만 작업의 직렬화가 없거나 자신의 Executor를 만들어 여기에 제공 할 수도 있습니다. 그러나 Javadocs에서 경고를주의 깊게 확인하십시오.

경고 : 스레드 풀에서 여러 작업을 병렬로 실행하도록 허용하는 것은 일반적으로 작업 순서가 정의되어 있지 않기 때문에 원하는 작업이 아닙니다. 예를 들어 이러한 작업을 사용하여 버튼 클릭으로 인해 파일을 작성하는 경우와 같이 일반적인 상태를 수정하는 경우 수정 순서가 보장되지 않습니다. 조심스럽게 작업하지 않으면 희귀 한 경우 새 버전의 데이터가 오래된 데이터로 덮어 쓰여 데이터가 손실되거나 안정성 문제가 발생할 수 있습니다. 이러한 변경은 연속적으로 수행하는 것이 가장 좋습니다. 이러한 작업이 플랫폼 버전과 상관없이 직렬화되도록 보장하려면이 함수를 SERIAL_EXECUTOR와 함께 사용할 수 있습니다.

한 가지 더 알아 두어야 할 것은 실행자 THREAD_POOL_EXECUTOR과 직렬 버전 SERIAL_EXECUTOR (AsyncTask의 기본값)를 제공하는 프레임 워크는 모두 정적 (클래스 수준 구조)이므로 응용 프로그램 프로세스에서 AsyncTask의 모든 인스턴스에서 공유된다는 것입니다.




Related

android multithreading android-asynctask