(37) Android+Javaでスレッドを使う場合のいろいろ

投稿者: | 2023年3月9日

184 views

この記事は最終更新から 437日 が経過しています。

1. やりたいこと

Androidプログラムを書いていて、以下の制約を意識したコードを書かなければならいことを知った。
制約 : UI描画処理は、アプリのメインスレッド上でのみ実行できる。

右往左往したので、少し整理しておく。

2. やってみる

後でいろいろと整理する。

Thread1 : Handlerを作成。1秒ごとに Main threadの Looperに postする。
Thread2 : Handlerを作成。1回だけ Main threadの Looperに postする。run()内部で1秒間 sleepしながら処理を繰り返し。
Thread3 : Sub threadを作成。run()内部で1秒間 sleepしながら処理を繰り返し。

・Thread2は、Handlerを使って Main threadの Looperに Postしているため、処理中は Main threadを占有する。
 → Thread1の処理は動けない。

・Thread3は、Main threadとは別に Sub threadを起動している。
 → Thread2と並行して動ける。
 → ただし、Main threadではないため、Android UIの制御ができない。
  → Thread3から Main threadの Looperに UI制御の Runnableを Postしている。

・Thread1と Thread3は別スレッドなので、Semaphoreで待ち合わせができる。

・Handler.post は Handlerクラスインスタンスを生成したスレッドに対して Runnableインスタンスを送る。

・Handlerは 1スレッドに 1個でよい。
 → Main threadに処理を postしたい場合、Main thread用に一つ Handlerを生成する、。
  → すべての Runnableはそこを指定して postする。

package com.example.testthread;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Handler;
import android.widget.TextView;

import java.util.concurrent.Semaphore;

public class MainActivity extends AppCompatActivity {
    private Semaphore smph = new Semaphore(1);
    private final Handler hMainThread = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        this.hMainThread.post(this.runThread1);
        this.hMainThread.post(this.runThread2);
        this.RunSubThread3();
    }

    ///////////////////////////////////////////////////////////////////////////
    // Thread1

    private final Runnable runThread1 = new Runnable() {
        private int i = 0;
        @Override
        public void run() {
            System.out.println("Thread1.START (" + i + ")>>>================================");
            try {
                smph.acquire();
                // Do something...
                smph.release();
            }catch(InterruptedException e){
                e.printStackTrace();
            }
            hMainThread.postDelayed(this, 1000);
            System.out.println("Thread1.END <<<==================================");
            this.i++;
        }
    };

    ///////////////////////////////////////////////////////////////////////////
    // Thread2
    private final Runnable runThread2 = new Runnable() {
        @Override
        public void run() {
/*
Main threadの Looperに Postされた処理
 → Main threadに queueingされた処理
  → Main threadの空き待ち後に実行される。*/
            for(int i = 0 ; i < 10 ; i++) {
                System.out.println("Thread2.START >>>*******************************");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Thread2.END <<<*********************************");
            }
        }
    };

    ///////////////////////////////////////////////////////////////////////////
    // Thread3
    private final Runnable runThread3B = new Runnable() {
        // Sub threadから Main threadに Postされて実行される処理
        @Override
        public void run() {
            TextView tv = findViewById(R.id.tv_1);
            tv.setText("Thread3 Done!");
        }
    };
    private final Runnable runThread3 = new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                if(i == 3){
                    try {
                        smph.acquire();
                    }catch(InterruptedException e){
                        e.printStackTrace();
                    }
                }
                if(i == 8){
                    smph.release();
                }
                System.out.println("Thread3.START (" + i + ")>>>------------------------------");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Thread3.END <<<--------------------------------");
            }
            // ここで UIにアクセスすると例外発生! → Main threadに handleを postする。
            //TextView tv = findViewById(R.id.tv_1);
            //tv.setText("Thread3 Done!");
            hMainThread.post(runThread3B);
        }
    };
    private void RunSubThread3() {
        Thread thread3 = new Thread(runThread3);
        thread3.start();
    }
}

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です


日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)