一手遮天 Android - 异步和多线程: Thread 演示 Object 的 wait() notify() notifyAll() 的使用

项目地址 https://github.com/webabcd/AndroidDemo
作者 webabcd

一手遮天 Android - 异步和多线程: Thread 演示 Object 的 wait() notify() notifyAll() 的使用

示例如下:

/async/ThreadDemo2.java

/**
 * 通过 Thread 演示 Object 的 wait() notify() notifyAll() 的使用
 *
 * 在多线程场景下,对 Object 加锁
 * 1、调用 Object 的 wait() 后,会阻塞当前线程
 * 2、调用 Object 的 notify() 后,多线程中的某一个被 wait() 阻塞的线程会被唤醒(具体是哪个线程会被唤醒是由系统决定的,无法预知)
 * 3、调用 Object 的 notifyAll() 后,多线程中的所有被 wait() 阻塞的线程都会被唤醒
 * 注:wait() 可以指定超时时间
 *
 *
 * 注:关于 Condition 的 await() signal() signalAll() 的说明,请参见“concurrent.LockDemo3”
 *
 *
 * 本示例通过生产者/消费者模型来演示 wait() notify() notifyAll() 的使用,同时演示 notify() 造成的死锁
 * 关于本例中的生产者/消费者模型,说明如下:
 * 1、Pool 是仓库,最多保存 1 件商品
 * 2、Producer 是生产者,如果仓库中没有商品的话,则每次生产 1 件商品放到仓库
 * 3、Consumer 是消费者,如果仓库中有商品的话,则每次从仓库拿走 1 件商品
 *
 * 运行示例后某一次的运行结果如下
 * p1 serialNo: 1
 * p1 notify
 * p1 wait
 * c1 serialNo: 1
 * c1 notify
 * c1 wait
 * p1 wait end
 * p1 serialNo: 2
 * p1 notify
 * p1 wait
 * c1 wait end
 * c1 serialNo: 2
 * c1 notify
 * c1 wait
 * c2 wait
 * p1 wait end
 * p1 serialNo: 3   // p1 生产了商品 3
 * p1 notify        // p1 通知可唤醒其他某一个线程
 * p1 wait          // p1 等待
 * c1 wait end      // c1 等待结束
 * c1 serialNo: 3   // c1 消费了商品 3
 * c1 notify        // c1 通知可唤醒其他某一个线程
 * c1 wait          // c1 等待
 * c2 wait end      // c2 等待结束
 * c2 wait          // c2 等待(此时 p1 c1 c2 都在等待,死锁了。如需避免此种情况,则将 notify() 改为 notifyAll() 即可)
 */

package com.webabcd.androiddemo.async;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import com.webabcd.androiddemo.R;

import java.util.LinkedList;
import java.util.List;

public class ThreadDemo2 extends AppCompatActivity {

    private final String LOG_TAG = "ThreadDemo2";

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

        sample();
    }

    private void sample() {
        Pool pool = new Pool();

        Producer p1 = new Producer(pool);
        p1.setName("p1");
        p1.start();

        Consumer c1 = new Consumer(pool);
        c1.setName("c1");
        c1.start();

        Consumer c2 = new Consumer(pool);
        c2.setName("c2");
        c2.start();
    }

    // 仓库
    class Pool {
        private List<Integer> list = new LinkedList<Integer>();
        private int max = 1;
        private int serialNo = 0;

        public int add(){
            synchronized (this){
                String threadName = Thread.currentThread().getName();
                while (list.size() >= max){
                    try{
                        Log.d(LOG_TAG, threadName + " wait");
                        this.wait(); // 可以指定超时时间
                        Log.d(LOG_TAG, threadName + " wait end");
                    }
                    catch (Exception e){
                        Log.d(LOG_TAG, e.toString());
                    }
                }

                serialNo++;
                list.add(new Integer(serialNo));
                Log.d(LOG_TAG, threadName + " serialNo: " + String.valueOf(serialNo));

                Log.d(LOG_TAG, threadName + " notify");
                this.notify();

                return serialNo;
            }
        }

        public int remove(){
            synchronized (this){
                String threadName = Thread.currentThread().getName();
                while (list.size() == 0){
                    try{
                        Log.d(LOG_TAG, threadName + " wait");
                        this.wait();
                        Log.d(LOG_TAG, threadName + " wait end");
                    }
                    catch (Exception e){
                        Log.d(LOG_TAG, e.toString());
                    }
                }

                int serialNo = list.remove(0);
                Log.d(LOG_TAG, threadName + " serialNo: " + String.valueOf(serialNo));

                Log.d(LOG_TAG, threadName + " notify");
                this.notify();

                return serialNo;
            }
        }
    }

    // 生产者
    class Producer extends Thread{
        private Pool pool;
        public Producer(Pool pool){
            this.pool = pool;
        }
        public void run(){
            while (true){
                int serialNo = pool.add();
            }
        }

    }

    // 消费者
    class Consumer extends Thread{
        private Pool pool;
        public Consumer(Pool pool){
            this.pool = pool;
        }
        public void run(){
            while (true){
                int serialNo = pool.remove();
            }
        }
    }
}

/layout/activity_async_threaddemo2.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/textView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="详见 java 代码" />

</LinearLayout>

项目地址 https://github.com/webabcd/AndroidDemo
作者 webabcd

posted @ 2021-06-02 09:32  webabcd  阅读(190)  评论(0编辑  收藏  举报