51歳からのプログラミング　備忘　マルチスレッド　迷走したので自分的にちょっとまとめ

迷走しました！
過去の関連記事もなんだか分からなかくなってるので、自分用の整理まとめメモ！なので他の記事と内容やコードが重複してます。

#Threadの概説
Androidは、基本的に**1つのLinuxプロセスに、一つのスレッド**を作って稼働するシングルスレッドモデルです（Manifestで定義すれば、別のプロセスに別のスレッドを作ってプログラムを稼働さたりも！）。

Androidでは、ユーザーエクスペリエンスを確保するため、ユーザー操作に影響を与えるような処理は、別スレッドで処理すべき、ってことになってて、あとUI部品はUIスレッドからしか操作できない、というルールもあります（UIはユーザーインターフェイス）。別スレッドはワーカースレッド（ユーザーインターフェイスを持たない）と呼ばれたりします。

別スレッドで処理させたりすると、UIスレッドとワーカースレッドとか、ワーカースレッド同士で通信する必要が生じます。で、UI部品はUIスレッドからしか操作できないので、ワーカースレッドからUI部品を更新する方法も知っとく必要があったりします。

通信のために、メインスレッド（UIスレッド）には、**Looper**が備わっていて、Looper内に**MessageQueue**を持ってます。MessageQueueは、他のスレッドから送られるMessageやRunnableを積み上げ保持し、Looperが取り出して処理します。

<strong><font color="#f55"><注意></font></strong>
ワーカースレッドの処理結果を、UIスレッドに渡して、UI部品を更新する作業は、ThreadクラスやRunnableインターフェイスを使ったマルチスレッド処理だと、複雑になりやすく、見通しが悪くなり、メンテナンスも困難になるって皆んなが言ってる。ハイコストなコードになってしまうのですね。

<font color="#05f">リファレンス的推奨はAsncTaskクラスです</font>。

マルチスレッド間で結果をやり取りできる通信手段はHandlerクラス！

#Threadの生成の概説
[詳しくは](https://qiita.com/old_cat/items/9d831ff30153786b94d8)
###ThreadはThreadクラスとRunnableインターフェイスのどっちを使う？

ThreadクラスはRunnableインターフェイスを継承したクラスで、Runnableと違って色んな定数やメソッドを持ってます。Threadクラスの定数やメソッドを使うのなら、Threadクラスを拡張して、特に使うメソッドとかがないのならRunnableを承継して、ワーカースレッドを作ればいいのかな？

###ワーカースレッドとUIスレッドの通信
ThreadクラスやRunnableインターフェースで作成したワーカースレッドから、処理の結果をUIスレッド（MainActivity)に引き渡すには、Viewクラスの**post(Runnable)**メソッド、**postDelayed(Runnable,long)**とかActivityクラスの**runOnUiThread(Runnable)**を使います。HandlerクラスでもOK。

#AnsyTaskとかHandlerとか

ThreadクラスやRunnableクラス以外の方法では、UIスレッドとの通信パッケージとなるAsyncTaskクラスがあります。またスレッド(UIスレッド以外も)間の通信を実現するHandlerクラスがあります。

##AsyncTask
[詳しくは！](https://qiita.com/old_cat/items/cf59e9d2f875fb7199e3)

ThreadクラスやRunnableインターフェイス以外の方法で、別スレッドからUI部品を操作するのなら、リファレンス推奨な**AsyncTask**！いやむしろ**AsyncTask**！

AsyncTaskは短時間処理に適してます。長時間スレッドで処理をさせたいのなら**Exesutor,ThreadPoolExecuter,FutureTask**など、java.util.concurrentパッケージで提供されるAPIsを検討してね！

AsyncTaskは並行処理によるエラーを避けるため、シングルスレッドで処理されます。並行処理をするのなら**THREAD_POOL_EXECUTOR**とともに、**executeOnExecutor**(java.util.concurrent.Executor,java.lang.Object[])を検討しましょう

####Andorid.os.AsyncTaskの用法
□　UIスレッド側
　 AsyncTask継承クラスをインスタンス化して**Execute()**を実行する

□　AsyncTask継承クラス(青字は必須)
　　**onPreExecute()**
　　<strong><font color="#05f">doInBackground()</font></strong>
　　　　// todo
　　　　**publishProgress()**
　　**onProgressUpdate()**
　　**onPostExecute()**

#####各メソッド

<table>
<tr><td>Execute()</td><td>doInBackground()を呼び出すdoInBackgorundが処理するタスクに必要な引数を渡す</td></tr>
<tr><td>onPreExecute()</td><td>Execute()の実行前にしたい処理を実行</td></tr>
<tr><td>doInBackgorund()</td><td>Execute()で起動し、Execute()から引き受ける引数で処理を実行</td></tr>
<tr><td>publichProgress</td><td>doInBackground()でタスクを処理してる間に、onProgressUpdate()でユーザーに表示したい文字やProgressを定義</td></tr>
<tr><td>onProgressUpdate</td><td>UI部品の操作をUIスレッドに渡す。</td></tr>
<tr><td>onPostExecute</td><td>doInBackground()から処理結果を受け取り、UI部品の操作をUIスレッドに渡す</td></tr>
</table>

##android.os.Handler　スレッド間の通信手段
[詳しくはこちらの　「Handlerまとめ的な」](https://qiita.com/old_cat/items/5624d592223e2434308a)

Handlerはマルチスレッドで（UIスレッドやワーカースレッド同士）で処理結果を送れます。

Handlerクラスをインスタンス化(handler)すると、インスタンス化したスレッドに、**LooperとMessageQueue**を備えます。

handlerは他のスレッドから使えるので、**post()、handle.obtainMessage()、handle.sendMessage()**などを使って、handlerを生成したメソッドにメッセージやRunnableのようなオブジェクトを送って、生成スレッドで処理を行います。

#サンプルコード
##Thread
[こちら](https://qiita.com/old_cat/items/9d831ff30153786b94d8)

##AsyncTask

####サンプルコード:execute()とdoInBackground()

- MainActivity.java<br>AsyncTask<>をサブクラス化し、execute()を実行する
- AsyncTask<>クラスを拡張して、MyAsyncTaskクラスを生成<br>doInBackground()は、MainActivity.javaのexecute()によって処理を実行する(todo)。doInBackground()はexecute()から引数を受け取るって処理に使うよ。

```java
public class MainActivity extends AppCompatActivity {

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

        // タスクインスタンスを生成。execute()で引数をonInBackground()に渡す
        // new MyAsyncTask<>.execute();  でもOK
        MyAsyncTask myAsyncTask = new MyAsyncTask<>;
        myAsyncTask.execute();

    }
}

class MyAsyncTask extends AsyncTask<Void,Void,Void> {
    @Override
    protected Void doInBackground(Void... aVoid) {
        // todo
        Log.d("msg","In MyAsyncTask");
        return null;
    }
}
```

####サンプルコード:幾つかメソッドを入れてみる

3秒毎にtextViewの表示を変えるコード

- **MyActivity.onCreate()**<br>myAsncTask.<font color="#05f">excute</font>("In doInBackground")
- **class MyAsyncTask**<br>
  - <font color="#05f">onPreExecute()</font><br>textView.setText("onPreExecute")
  - <font color="#05f">doInBackground()</font><br>sleep(1000*3)　->　<font color ="#05f">publishProgress</font>(string[0])　->　sleep(1000*3)　->　<font color="#05f">return "End doInBackground"</font>
  - <font color="#05f">onProgressUpdate()</font><br>textView.setText(string[0])
  - <font color="#05f">onPostExecute()</font><br>textView.setText(s)

```java
public class MainActivity extends AppCompatActivity {

    TextView textView;

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

        textView = findViewById(R.id.textView);

        // タスクインスタンスを生成。execute()で引数をonInBackground()に渡す
        // new MyAsyncTask<>.execute();  でもOK
        MyAsyncTask myAsyncTask = new MyAsyncTask<>;
        // doInBackground()に文字列("In doInBackground")を渡して
        // onPreExecute()の処理後に、doInBackground()を実行
        myAsyncTask.execute("In doInBackground");

    }

    class MyAsyncTask extends AsyncTask<String,String, String> {

        // execute("In doInBackground")処理前に実行。UIスレッドのtextViewに表示
        @Override
        protected void onPreExecute(){
            textView.setText("onPreExecute");
        }

        // execute()から文字列"In doInBackground"を受け取る
        @Override
        protected String doInBackground(String... string) {

            // 3秒待機
            try {
                sleep(1000*3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // doInBackground処理中に、textViewを表示させるonPublishUpdate()を呼ぶ
            publishProgress(string[0]);

            // 3秒待機
            try {
                sleep(1000*3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // onPostExecute()に文字列"End doInBackground"を渡す
            return "End doInBackground";
        }

        // doInBackground内のpublishProgress()から文字列を受け取り、UIスレッドのtextViewに表示
        protected void onProgressUpdate(String... string){
            textView.setText(string[0]);
        }

        // doInBackground()からreturn値("End doInBackground")を受け取り、UIスレッドのtextViewに表示
        @Override
        protected void onPostExecute(String s){
            textView.setText(s);
        }
    }
}
```

##Handler

<Messageを使った通信例>
####HandlerとMessageの事例１
```java:Message
public class MainActivity extends AppCompatActivity {

    TextView textView;

    // UIスレッド(MainActivity)でHandlerインスタンスを生成します
    // これでMessageQueueもLooperもUIスレッドの物だね
    // インスタンス handler は別スレッドから参照可能なので
    // 別スレッドで handler を参照して、messageを載せれば
    // UIスレッド（MainActivity)でLooperが処理してくれるんだぜ！
    // カッコいいじゃん！！
    // では、handler さんに登場願います！
    Handler handler = new MyHandler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.textView1);

        MyLovelyMessage();
    }

    private void MyLovelyMessage() {
        // UIスレッド（MainActivity)で生成した handler にアクセスし
        // handler に Messageを載せて sendMessage!
        // これでUIスレッドのLooperが上手くやってくれるはず！
        Message message = handler.obtainMessage(1);
        handler.sendMessage(message);
    }

    class MyHandler extends Handler{
        @Override
        public void handleMessage(Message message){
            // handle が UIスレッドで何をするかを定義する
            // Looperによって自動的に実行されるよ！
            String msg = String.valueOf(message.what);
            textView.setText(msg);
        }
    }
}

```
上のコードを内部関数的にシンプルに

```java:Message
public class MainActivity extends AppCompatActivity {

    TextView textView;

    Handler handler = new Handler(){
      @Override
      public void handleMessage(Message message){
          String msg = String.valueOf(message.what);
          textView.setText(msg);
      }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.textView1);

        MyLovelyRunnable();
    }

    private void MyLovelyRunnable() {
        Message message = handler.obtainMessage(1);
        handler.sendMessage(message);
    }
}
```
####HandlerとRunnableを使った事例

```java
public class MainActivity extends AppCompatActivity {

    TextView textView;

    // HandlerをUIスレッド(MainAvtivity.class)で生成します
    // これで、MessageQueue も Looper も、このスレッド(UIスレッド)に関連付けれます
    //
    // Handlerインスタンスは、他のスレッドからも参照できるので
    // 他のスレッドで、インスタンス handler を使って
    // Runnableをこのスレッド(UIスレッド)に渡せば
    // このスレッド(UIスレッド側)でRunnableを実行できるようになります
    // 素敵ですね！
    // ではHandlerのインスタンスを生成しましょう！！
    Handler handler = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.textView1);

        MyLovelyHandler();

    }

    private void MyLovelyHandler(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                // UIスレッド(MainActivity)で生成したHandlerのインスタンスは
                // 他のスレッドからでも参照可能です
                // インスタンスhandlerにRunnableを載せて
                // UIスレッド（MainActivity)に渡して処理してもらいましょう！
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        textView.setText("I Love Handler");
                    }
                });
            }
        }).start();
    }
}
```