programing

여러 비동기 작업을 동시에 실행할 수 있습니까?

megabox 2023. 9. 16. 08:54
반응형

여러 비동기 작업을 동시에 실행할 수 있습니까?

동시에 2개의 Async Task를 실행하려고 합니다. (플랫폼은 Android 1.5, HTC Hero입니다.그러나 첫 번째 것만 실행됩니다.다음은 제 문제를 설명하는 간단한 토막입니다.

public class AndroidJunk extends Activity {
 class PrinterTask extends AsyncTask<String, Void, Void> {
     protected Void doInBackground(String ... x) {
      while (true) {
       System.out.println(x[0]);
       try {
        Thread.sleep(1000);
       } catch (InterruptedException ie) {
        ie.printStackTrace();
       }
      }
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        new PrinterTask().execute("bar bar bar");
        new PrinterTask().execute("foo foo foo");

        System.out.println("onCreate() is done.");
    }
}

예상되는 출력은 다음과 같습니다.

onCreate() is done.
bar bar bar
foo foo foo
bar bar bar
foo foo foo

뭐 이런 거.하지만 제가 얻은 것은 다음과 같습니다.

onCreate() is done.
bar bar bar
bar bar bar
bar bar bar

두 번째 AsyncTask는 실행되지 않습니다.execute() 문의 순서를 변경하면 foo 작업만 출력됩니다.

제가 뭔가 명백한 걸 놓치고 있는 건가요? 아니면 바보 같은 짓을 하고 있는 건가요?두 개의 비동기 작업을 동시에 실행할 수는 없습니까?

편집: 해당 폰이 안드로이드 1.5를 실행한다는 것을 알고 문제 설명을 업데이트했습니다.따라서.안드로이드 2.1을 실행하는 HTC Hero에 대해서는 이 문제가 없습니다.음...

AsyncTask는 DoInBackground()의 작업을 실행하기 위해 스레드 풀 패턴을 사용합니다.문제는 초기 안드로이드 OS 버전에서 풀 크기가 1에 불과했다는 것입니다. 이는 다수의 비동기 작업에 대해 병렬 계산이 없음을 의미합니다.그러나 나중에 수정한 결과 크기가 5이므로 최대 5개의 비동기 작업을 동시에 실행할 수 있습니다.안타깝게도 정확히 어떤 버전으로 바꿨는지 기억이 나지 않습니다.

업데이트:

다음은 현재 (2012-01-27) API에서 말하는 내용입니다.

처음 도입되었을 때, 비동기 작업은 단일 백그라운드 스레드에서 직렬로 실행되었습니다.도넛을 시작으로 여러 작업이 병렬로 작동할 수 있도록 스레드 풀로 변경되었습니다.HONEY 이후에는 병렬 실행으로 인한 일반적인 응용 프로그램 오류를 방지하기 위해 이를 다시 단일 스레드로 변경할 계획입니다.진정으로 병렬 실행을 원하는 경우, 이 메서드의 executeOnExecutor(Executor, Params...) 버전을 TRADE_POOL_EXECUTOR와 함께 사용할 수 있습니다. 그러나 사용에 대한 경고는 주석을 참조하십시오.

도넛은 안드로이드 1.6, 허니콤은 안드로이드 3.0입니다.

업데이트: 2

kabukoMar 7 2012 at 1:27.

"수풀의 경우(하여 3까지), 에 실행되는 의 수에 달라지지만 " 중인 작업 수는 "실행 중인 작업 수에 따라 달라지지만 "실행 중인 작업 수"의 API 수를 하지 못한 1.6 작업 수). 동시에 실행되는 AsyncTasks의 수는 실행을 위해 이미 전달된 작업의 수에 따라 달라지지만 완료되지 않은 작업의 수에 따라 달라집니다.doInBackground() 아직.

이것은 2.2에 저에 의해 테스트/확인되었습니다.자 [ AsyncTask(비동기 작업)]고 [ ]합니다 [ ]에서 1초만 합니다.doInBackground()작업을 합니다. 비동기 작업은 지연된 작업을 저장하기 위해 내부적으로 고정 크기 대기열을 사용합니다.대기열 크기는 기본적으로 10입니다.의 사용자 가 15개의 작업의자로의음하면 5개의 합니다.doInBackground() thread 를 을 입니다 는 입니다 을 .처음 5개 중 하나가 완료되면 작업자 스레드가 해제되면 대기열의 작업이 실행을 시작합니다.따라서 이 경우 최대 5개의 작업이 동시에 실행됩니다. 지정 나 16자을로면가 5자다에정음정r다rr정자가음lnf5n6s의r면나ut doInBackground()즉시 10 에 에는 16 됩니다 이 되어 가 는 됩니다 이 되어 가 에는 에 는 따라서 이 경우 최대 6개의 작업이 동시에 실행됩니다.

동시에 실행할 수 있는 태스크의 수에는 한계가 있습니다.AsyncTask최대 작업자 스레드 수가 제한된 스레드 풀 실행기(128)를 사용하며 지연된 작업 대기열의 크기는 고정된 10입니다. 138개 이상의 사용자 지정 작업을 실행하려고 하면 앱이 충돌합니다.java.util.concurrent.RejectedExecutionException.

부터는 API를 통해 풀 할 수 . 3.0부터는 API를 통해 정의 풀 실행기를 사용할 수 있습니다.AsyncTask.executeOnExecutor(Executor exec, Params... params) 않을 할 수 .예를 들어, 기본값 10이 필요하지 않을 경우 지연된 작업 대기열의 크기를 구성할 수 있습니다.

@언급한처럼 @Knossos 한 처럼 이 할 이 을 사용할 수 있는 이 있습니다.AsyncTaskCompat.executeParallel(task, params);지원 v.4 라이브러리에서 API 수준을 방해하지 않고 작업을 병렬로 실행할 수 있습니다.0.0에서 되지 않게 되었습니다. API에서 26.0.0지다게상벨더는이id다ncs게e지d6는상벨더il이

업데이트: 3

다음은 다양한 작업, 직렬 대 병렬 실행으로 실행할 수 있는 간단한 테스트 앱입니다. https://github.com/vitkhudenko/test_asynctask

업데이트: 4 (이를 지적해주신 @penkzhou 감사합니다)

4 Android 4.4 AsyncTaskUPDATE: 2 섹션에서 설명한 것과 다르게 동작합니다.예방할 수 있는 해결책이 있습니다.AsyncTask너무 많은 스레드를 만드는 것에서.

4 19) 버전 Android 4.4 (API 19)AsyncTask과 같은를 가지고 있었습니다.

private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;
private static final BlockingQueue<Runnable> sPoolWorkQueue =
        new LinkedBlockingQueue<Runnable>(10);

Android 4.4(API 19)에서 위 필드는 다음과 같이 변경됩니다.

private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final BlockingQueue<Runnable> sPoolWorkQueue =
        new LinkedBlockingQueue<Runnable>(128);

이렇게 변경하면 큐의 크기가 128개 항목으로 늘어나고 최대 스레드 수가 CPU 코어 수 * 2 + 1로 줄어듭니다. 앱은 여전히 동일한 수의 작업을 제출할 수 있습니다.

이를 통해 API 4+(Android 1.6+)를 사용하는 모든 안드로이드 버전에서 병렬 실행이 가능합니다.

@TargetApi(Build.VERSION_CODES.HONEYCOMB) // API 11
void startMyTask(AsyncTask asyncTask) {
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
        asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
    else
        asyncTask.execute(params);
}

이것은 아리메드의 훌륭한 대답을 요약한 것입니다.

프로젝트 빌드 대상으로 API 레벨 11 이상을 사용할 수 있도록 하십시오.이클립스에서, 그것은Project > Properties > Android > Project Build Target. 이렇게 하면 하위 API 수준에 대한 하위 호환성이 깨지지 않습니다.걱정하지 마세요. 나중에 도입된 기능을 실수로 사용하면 린트 오류가 발생합니다.minSdkVersion을 꼭 . 보다 에 되는 을 하려면 하려면 을 보다 되는 에 minSdkVersion, 주석을 사용하여 이러한 오류를 억제할 수 있지만 이 경우 호환성에 대해 직접 주의해야 합니다.이것은 바로 위의 코드 조각에서 일어난 일입니다.

2022년 업데이트

:AsyncTasks오래전에 감가상각을 당했습니다만약 당신이 Kotlin을 사용한다면, Kotlin Coroutines를 사용하는 것을 추천하고, 당신이 프로젝트에서 Java를 사용하는 것에 의존한다면, 대안은 다음을 사용하는 것입니다.Executorsjava.util.concurrent. (출처)

@sulai 제안을 보다 일반적으로 만들기:

@TargetApi(Build.VERSION_CODES.HONEYCOMB) // API 11
public static <T> void executeAsyncTask(AsyncTask<T, ?, ?> asyncTask, T... params) {
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
        asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
    else
        asyncTask.execute(params);
}   

@Arhimed's의 완벽한 답변에 최신 업데이트(UPDATE 4)를 @sulai의 아주 좋은 요약에 포함하는 것입니다.

void doTheTask(AsyncTask task) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // Android 4.4 (API 19) and above
        // Parallel AsyncTasks are possible, with the thread-pool size dependent on device
        // hardware
        task.execute(params);
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { // Android 3.0 to
        // Android 4.3
        // Parallel AsyncTasks are not possible unless using executeOnExecutor
        task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
    } else { // Below Android 3.0
        // Parallel AsyncTasks are possible, with fixed thread-pool size
        task.execute(params);
    }
}

안드로이드 개발자의 비트맵 로드 예제에서는 사용자 지정 비동기 작업(젤리빈에서 복사)을 효율적으로 사용하므로 < 11보다 낮은 apis에서 executeOnExecutor를 사용할 수 있습니다.

http://developer.android.com/training/displaying-bitmaps/index.html

코드를 다운로드하고 util package로 이동합니다.

가능합니다.저의 안드로이드 기기 버전은 4.0.4와 안드로이드.os입니다.빌드.VERSION.SDK_INT는 15입니다.

스피너가 3개 있습니다.

Spinner c_fruit=(Spinner) findViewById(R.id.fruits);
Spinner c_vegetable=(Spinner) findViewById(R.id.vegetables);
Spinner c_beverage=(Spinner) findViewById(R.id.beverages);

그리고 저는 Async-Tack 수업도 있습니다.

여기 스피너 로딩 코드가 있습니다.

RequestSend reqs_fruit = new RequestSend(this);
reqs_fruit.where="Get_fruit_List";
reqs_fruit.title="Loading fruit";
reqs_fruit.execute();

RequestSend reqs_vegetable = new RequestSend(this);
reqs_vegetable.where="Get_vegetable_List";
reqs_vegetable.title="Loading vegetable";
reqs_vegetable.execute();

RequestSend reqs_beverage = new RequestSend(this);
reqs_beverage.where="Get_beverage_List";
reqs_beverage.title="Loading beverage";
reqs_beverage.execute();

완벽하게 작동합니다.스피너들이 하나둘씩 장전을 했어요.OnExecutor를 실행하지 않았습니다.

여기 제 비동기 작업 수업이 있습니다.

public class RequestSend  extends AsyncTask<String, String, String > {

    private ProgressDialog dialog = null;
    public Spinner spin;
    public String where;
    public String title;
    Context con;
    Activity activity;      
    String[] items;

    public RequestSend(Context activityContext) {
        con = activityContext;
        dialog = new ProgressDialog(activityContext);
        this.activity = activityContext;
    }

    @Override
    protected void onPostExecute(String result) {
        try {
            ArrayAdapter<String> adapter = new ArrayAdapter<String> (activity, android.R.layout.simple_spinner_item, items);       
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            spin.setAdapter(adapter);
        } catch (NullPointerException e) {
            Toast.makeText(activity, "Can not load list. Check your connection", Toast.LENGTH_LONG).show();
            e.printStackTrace();
        } catch (Exception e)  {
            Toast.makeText(activity, "Can not load list. Check your connection", Toast.LENGTH_LONG).show();
            e.printStackTrace();
        }
        super.onPostExecute(result);

        if (dialog != null)
            dialog.dismiss();   
    }

    protected void onPreExecute() {
        super.onPreExecute();
        dialog.setTitle(title);
        dialog.setMessage("Wait...");
        dialog.setCancelable(false); 
        dialog.show();
    }

    @Override
    protected String doInBackground(String... Strings) {
        try {
            Send_Request();
            } catch (NullPointerException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        return null;
    }

    public void Send_Request() throws JSONException {

        try {
            String DataSendingTo = "http://www.example.com/AppRequest/" + where;
            //HttpClient
            HttpClient httpClient = new DefaultHttpClient();
            //Post header
            HttpPost httpPost = new HttpPost(DataSendingTo);
            //Adding data
            List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);

            nameValuePairs.add(new BasicNameValuePair("authorized","001"));

            httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
            // execute HTTP post request
            HttpResponse response = httpClient.execute(httpPost);

            BufferedReader reader;
            try {
                reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
                StringBuilder builder = new StringBuilder();
                String line = null;
                while ((line = reader.readLine()) != null) {
                    builder.append(line) ;
                }

                JSONTokener tokener = new JSONTokener(builder.toString());
                JSONArray finalResult = new JSONArray(tokener);
                items = new String[finalResult.length()]; 
                // looping through All details and store in public String array
                for(int i = 0; i < finalResult.length(); i++) {
                    JSONObject c = finalResult.getJSONObject(i);
                    items[i]=c.getString("data_name");
                }

            } catch (ClientProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

병렬로 를 로 를 해야 하려면 해야 를 로 를 하려면 executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "your task name")Android 버전 3.0 이후; 그러나 이 방법은 Android 3.0 이전 및 1.6 이후에는 존재하지 않습니다. 이 방법은 자체적으로 병렬로 실행되므로 다른 Android 버전에서 예외를 허용하지 않도록 프로젝트에서 자신의 AsyncTask 클래스를 사용자 지정하는 것이 좋습니다.

언급URL : https://stackoverflow.com/questions/4068984/running-multiple-asynctasks-at-the-same-time-not-possible

반응형