Android生产者消费者

学习多线程同步的生产者和消费者问题,目标是两个线程共同访问一个仓库,一个生产,一个消费,仓库大小为10,总共要生产50个产品,代码如下:

package com.example.producercomsumer;

import java.util.LinkedList;
import java.util.Random;

import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;

public class MainActivity extends Activity {

	public static final String TAG = "";
	public static final int FULL_SIZE = 10;
	private LinkedList mStorage = new LinkedList();
	private static final int TOTAL_NUM = 50;

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

		new Producer().start();
		new Comsumer().start();
	}

	class Producer extends Thread {
		int total = 0;

		public void run() {

			Log.d(TAG, "Start Produce>>>>>>>>>>>>>>>");
			while (total < TOTAL_NUM) {

				synchronized (mStorage) {
					while (mStorage.size() == FULL_SIZE) {
						try {
							mStorage.wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}

					String product = "PRODUCT("  + new Random().nextInt() + ")";
					total++;

					mStorage.add(product);

					Log.d(TAG, "Produce:" + product + " storage size:" + mStorage.size() + " , total:" + total);

					mStorage.notify();

					Thread.yield();
				}

			}
//			Log.d(TAG, "End Produce<<<<<<<<<<<<<<<");
		}
	}

	class Comsumer extends Thread {
		public void run() {

			while (true) {
				synchronized (mStorage) {
					while (mStorage.size() == 0) {
						try {
							mStorage.wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}

					String product = mStorage.removeFirst();
					Log.d(TAG, "Consume : " + product + " storage size:" + mStorage.size());

					mStorage.notify();

					Thread.yield();

				}
			}
		}
	}
}

运行结果:

D/ ( 8368): Start Produce>>>>>>>>>>>>>>>
D/ ( 8368): Produce:PRODUCT(638723307) storage size:1 , total:1
D/ ( 8368): Produce:PRODUCT(1004619511) storage size:2 , total:2
D/ ( 8368): Produce:PRODUCT(-498194369) storage size:3 , total:3
D/ ( 8368): Produce:PRODUCT(723383389) storage size:4 , total:4
D/ ( 8368): Produce:PRODUCT(567560084) storage size:5 , total:5
D/ ( 8368): Produce:PRODUCT(1379010839) storage size:6 , total:6
D/ ( 8368): Produce:PRODUCT(1154317481) storage size:7 , total:7
D/ ( 8368): Produce:PRODUCT(941936088) storage size:8 , total:8
D/ ( 8368): Produce:PRODUCT(2022311000) storage size:9 , total:9
D/ ( 8368): Produce:PRODUCT(1809929607) storage size:10 , total:10
I/ZDClock ( 5221): ScheduleReceiver finish…
D/ ( 8368): Consume : PRODUCT(638723307) storage size:9
D/ ( 8368): Produce:PRODUCT(-1766711493) storage size:10 , total:11
D/ ( 8368): Consume : PRODUCT(1004619511) storage size:9
D/ ( 8368): Produce:PRODUCT(-549750722) storage size:10 , total:12
D/ ( 8368): Consume : PRODUCT(-498194369) storage size:9
D/ ( 8368): Produce:PRODUCT(-1021068124) storage size:10 , total:13
D/ ( 8368): Consume : PRODUCT(723383389) storage size:9
D/ ( 8368): Produce:PRODUCT(-1835566222) storage size:10 , total:14
D/ ( 8368): Consume : PRODUCT(567560084) storage size:9
D/ ( 8368): Produce:PRODUCT(2075806421) storage size:10 , total:15
D/ ( 8368): Consume : PRODUCT(1379010839) storage size:9
D/ ( 8368): Produce:PRODUCT(-1123780757) storage size:10 , total:16
D/ ( 8368): Consume : PRODUCT(1154317481) storage size:9
D/ ( 8368): Produce:PRODUCT(-1505451665) storage size:10 , total:17
D/ ( 8368): Consume : PRODUCT(941936088) storage size:9
D/ ( 8368): Produce:PRODUCT(-310421582) storage size:10 , total:18
D/ ( 8368): Consume : PRODUCT(2022311000) storage size:9
D/ ( 8368): Produce:PRODUCT(-952567496) storage size:10 , total:19
D/ ( 8368): Consume : PRODUCT(1809929607) storage size:9
D/ ( 8368): Produce:PRODUCT(207450438) storage size:10 , total:20
D/ ( 8368): Consume : PRODUCT(-1766711493) storage size:9
D/ ( 8368): Produce:PRODUCT(-174220471) storage size:10 , total:21
D/ ( 8368): Consume : PRODUCT(-549750722) storage size:9
D/ ( 8368): Produce:PRODUCT(-987564322) storage size:10 , total:22
D/ ( 8368): Consume : PRODUCT(-1021068124) storage size:9
D/ ( 8368): Produce:PRODUCT(-1369619979) storage size:10 , total:23
D/ ( 8368): Consume : PRODUCT(-1835566222) storage size:9
D/ ( 8368): Produce:PRODUCT(120127762) storage size:10 , total:24
D/ ( 8368): Consume : PRODUCT(2075806421) storage size:9
D/ ( 8368): Produce:PRODUCT(-263466892) storage size:10 , total:25
D/ ( 8368): Consume : PRODUCT(-1123780757) storage size:9
D/ ( 8368): Produce:PRODUCT(853459165) storage size:10 , total:26
D/ ( 8368): Consume : PRODUCT(-1505451665) storage size:9
D/ ( 8368): Produce:PRODUCT(471788256) storage size:10 , total:27
D/ ( 8368): Consume : PRODUCT(-310421582) storage size:9
D/ ( 8368): Produce:PRODUCT(1667203089) storage size:10 , total:28
D/ ( 8368): Consume : PRODUCT(-952567496) storage size:9
D/ ( 8368): Produce:PRODUCT(1285532180) storage size:10 , total:29
D/ ( 8368): Consume : PRODUCT(207450438) storage size:9
D/ ( 8368): Produce:PRODUCT(-737646103) storage size:10 , total:30
D/ ( 8368): Consume : PRODUCT(-174220471) storage size:9
D/ ( 8368): Produce:PRODUCT(-1108928791) storage size:10 , total:31
D/ ( 8368): Consume : PRODUCT(-987564322) storage size:9
D/ ( 8368): Produce:PRODUCT(8382015) storage size:10 , total:32
D/ ( 8368): Consume : PRODUCT(-1369619979) storage size:9
D/ ( 8368): Produce:PRODUCT(-373673643) storage size:10 , total:33
D/ ( 8368): Consume : PRODUCT(120127762) storage size:9
D/ ( 8368): Produce:PRODUCT(885224758) storage size:10 , total:34
D/ ( 8368): Consume : PRODUCT(-263466892) storage size:9
D/ ( 8368): Produce:PRODUCT(480084166) storage size:10 , total:35
D/ ( 8368): Consume : PRODUCT(853459165) storage size:9
D/ ( 8368): Produce:PRODUCT(1689349959) storage size:10 , total:36
D/ ( 8368): Consume : PRODUCT(471788256) storage size:9
D/ ( 8368): Produce:PRODUCT(277721569) storage size:10 , total:37
D/ ( 8368): Consume : PRODUCT(1667203089) storage size:9
D/ ( 8368): Produce:PRODUCT(-105873084) storage size:10 , total:38
D/ ( 8368): Consume : PRODUCT(1285532180) storage size:9
D/ ( 8368): Produce:PRODUCT(1088002753) storage size:10 , total:39
D/ ( 8368): Consume : PRODUCT(-737646103) storage size:9
D/ ( 8368): Produce:PRODUCT(607836125) storage size:10 , total:40
D/ ( 8368): Consume : PRODUCT(-1108928791) storage size:9
D/ ( 8368): Produce:PRODUCT(1803250958) storage size:10 , total:41
D/ ( 8368): Consume : PRODUCT(8382015) storage size:9
D/ ( 8368): Produce:PRODUCT(1369254199) storage size:10 , total:42
D/ ( 8368): Consume : PRODUCT(-373673643) storage size:9
D/ ( 8368): Produce:PRODUCT(-1414804167) storage size:10 , total:43
D/ ( 8368): Consume : PRODUCT(885224758) storage size:9
D/ ( 8368): Produce:PRODUCT(-1863036635) storage size:10 , total:44
D/ ( 8368): Consume : PRODUCT(480084166) storage size:9
D/ ( 8368): Produce:PRODUCT(1626666537) storage size:10 , total:45
D/ ( 8368): Consume : PRODUCT(1689349959) storage size:9
D/ ( 8368): Produce:PRODUCT(1244610879) storage size:10 , total:46
D/ ( 8368): Consume : PRODUCT(277721569) storage size:9
D/ ( 8368): Produce:PRODUCT(-1931891364) storage size:10 , total:47
D/ ( 8368): Consume : PRODUCT(-105873084) storage size:9
D/ ( 8368): Produce:PRODUCT(1981405023) storage size:10 , total:48
D/ ( 8368): Consume : PRODUCT(1088002753) storage size:9
D/ ( 8368): Produce:PRODUCT(-1218182155) storage size:10 , total:49
D/ ( 8368): Consume : PRODUCT(607836125) storage size:9
D/ ( 8368): Produce:PRODUCT(-1601776808) storage size:10 , total:50
D/ ( 8368): Consume : PRODUCT(1803250958) storage size:9
D/ ( 8368): Consume : PRODUCT(1369254199) storage size:8
D/ ( 8368): Consume : PRODUCT(-1414804167) storage size:7
D/ ( 8368): Consume : PRODUCT(-1863036635) storage size:6
D/ ( 8368): Consume : PRODUCT(1626666537) storage size:5
D/ ( 8368): Consume : PRODUCT(1244610879) storage size:4
D/ ( 8368): Consume : PRODUCT(-1931891364) storage size:3
D/ ( 8368): Consume : PRODUCT(1981405023) storage size:2
D/ ( 8368): Consume : PRODUCT(-1218182155) storage size:1
D/ ( 8368): Consume : PRODUCT(-1601776808) storage size:0

 

发现是这样wait的:

				while (mStorage.size() == FULL_SIZE) {
					try {
						mSync.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}

好奇为什么用while而不用if,actually, 当我把它改为if后,程序仍然可以正常运行。
像这样:

	class Producer extends Thread {
		int total = 0;

		public void run() {

			Log.d(TAG, "Start Produce》》》》》》》》》》》》》》》》》》》》");
			while (total < TOTAL_NUM) {

				synchronized (mSync) {
					if (mStorage.size() == FULL_SIZE) {
						try {
							mSync.wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}

					String product = "PRODUCT("  + new Random().nextInt() + ")";
					total++;

					mStorage.add(product);

					Log.d(TAG, "Produce:" + product + " storage size:" + mStorage.size() + " , total:" + total);

					mSync.notify();

					Thread.yield();
				}

			}
			Log.d(TAG, "End Produce《《《《《《《《《《《《《《《");
		}
	}

	class Comsumer extends Thread {
		public void run() {

			while (true) {
				synchronized (mSync) {
					if (mStorage.size() == 0) {
						try {
							mSync.wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}

					String product = mStorage.removeFirst();
					Log.d(TAG, "Consume : " + product + " storage size:" + mStorage.size());

					mSync.notify();

					Thread.yield();

				}
			}
		}
	}

现在尝试把事情变得好玩点,添加一个消费者,变成一个人生产,两个人消费:

Consumer:

	class Comsumer extends Thread {

		private String mName;

		public Comsumer (String name){
			mName = name;
		}

		public void run() {

			while (true) {
				synchronized (mSync) {
					if (mStorage.size() == 0) {
						try {
							mSync.wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}

					String product = mStorage.removeFirst();
					Log.d(TAG, "Consumer " + mName + " consume " + product + " storage size:" + mStorage.size());

					mSync.notify();

					Thread.yield();

				}
			}
		}
	}

这样调用:

		new Producer().start();
		new Comsumer("herbert").start();
		new Comsumer("wellings").start();

OK, 运行,第一次没问题,都被herbert消费了,第二次也没问题,wellings也消费了10个,第三次,程序挂了。

W/dalvikvm( 3552): threadid=14: thread exiting with uncaught exception (group=0x40a4f300)
E/AndroidRuntime( 3552): FATAL EXCEPTION: Thread-694
E/AndroidRuntime( 3552): java.util.NoSuchElementException
E/AndroidRuntime( 3552): 	at java.util.LinkedList.removeFirstImpl(LinkedList.java:689)
E/AndroidRuntime( 3552): 	at java.util.LinkedList.removeFirst(LinkedList.java:676)
E/AndroidRuntime( 3552): 	at com.example.producercomsumer.MainActivity$Comsumer.run(MainActivity.java:85)
W/ActivityManager( 1848):   Force finishing activity com.example.producercomsumer/.MainActivity

什么情况? 加了打印消息后看得更清楚:

			String product = null;
			try {
							product = mStorage.removeFirst();
			} catch (Exception e) {
				e.printStackTrace();
			}
			Log.d(TAG, "Consumer " + mName + " consume " + product + " storage size:" + mStorage.size());
D/        (10638): Consumer herbert consume PRODUCT(-959284557) storage size:0
W/System.err(10638): java.util.NoSuchElementException
W/System.err(10638): 	at java.util.LinkedList.removeFirstImpl(LinkedList.java:689)
W/System.err(10638): 	at java.util.LinkedList.removeFirst(LinkedList.java:676)
W/System.err(10638): 	at com.example.producercomsumer.MainActivity$Comsumer.run(MainActivity.java:85)
D/        (10638): Consumer wellings consume null storage size:0

原来是wellings试图去空仓库里拿东西,不是有if (仓库为空) wait(); 吗? 答案是有两个消费线程被notify,只有先被nogify的那个线程可以拿到最后一个,后面的线程也被notify到了(说明一个问题:notify()会叫醒所有wait()的线程,相当于notifyAll()?) 但是拿不东西就会出错。现在才发现while() if()的区别,while()被notify到后,会循环到前面再检测一次仓库是否为空,而if()不会再次检测,这就是为什么我看到的代码都是用while的原因。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值