⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 consumer.java

📁 一个简单的Java多线程的小例子。 a) Producer 生产 String
💻 JAVA
字号:
/**
 * 
 */
package problem8_3;

import java.util.*;

/**
 * @author Administrator
 *
 */
//实现Runnable接口,而不是继承Thread类,主要是为了方便共享数据
public class Consumer implements Runnable{
//	生产者的pStrList与消费者的cStrList是同步的,因为等号赋值相当于引用
	StrArray cStrList;
//	outputNum定义消费者已经消费多少数据
	int outputNum;
//	consumeSize定义消费者总共可以消费多少数据
	int consumeSize;
	
	public Consumer(StrArray aStrArray,int i) {
		cStrList=aStrArray;
		consumeSize=i;
		outputNum=0;
	}
	
	public Consumer() {
		
	}
	
	public void run() /*throws InterruptedException*/{
//		如果Producer没有生产数据或数据已被消费完,则消费者等待
		try{if(cStrList.stringArray.size()==0) Thread.sleep(10);
		
		} catch(InterruptedException e){
			System.out.println("Consumer can not sleep");
		}
//		同步是为了防止Str.remove()时抛出异常,因为可能同时有两个Consumer线程在修改Str,而这时不允许的(使用Iterator类的remove()只能避免在单线程中抛出异常),详情见下面的注释
//		注意synchronized括号内的参数必须是本类的数据成员
		synchronized (cStrList) {
//			注意,cStrList.stringArray.size()会随着str.remove()而改变
			if (cStrList.stringArray.size() != 0) {
				Iterator Str = cStrList.stringArray.iterator();
				while (Str.hasNext()) {
					System.out.println(Thread.currentThread().getName()
							+ " consume " + Str.next());
					Str.remove();
					outputNum++;
					if (outputNum == consumeSize) {
						System.out.println(Thread.currentThread().getName()
								+ "消费" + consumeSize + "个数据完毕,结束消费");
//						退出while循环,从而退出这个线程
						break;
					}
				}

			}
		}
//		为了方便调试时设置断点用
		System.out.println(Thread.currentThread().getName()+" end");
	}

}

//在Java里,当使用一个迭代器去迭代一个对象(Collection或是Map等等)时,如果在迭代过程中,对象被修改了,那么就会抛出ConcurrentModificationException异常。那么,我们如何避免这种情况,去安全的使用迭代器呢?
//
//当我们需要在迭代的时候修改这个对象时,我们必须使用迭代器本身的API去修改这个对象,而不能用对象自己的API去修改。比如说,我们想删除对象里满足某种条件的元素时,我们可以用:
//
//Iterator it = map.keySet().iterator();
//while(it.hasNext()) {
//it.next();
//if(somecondition)it.remove();
//}
//
//使用Iterator本身的remove方法时,它不仅会删除对象里的元素,同时也会更新迭代器本身。但是如果使用对象本身的API去修改的话:
//
//Iterator it = map.keySet().iterator();
//while(it.hasNext()) {
//if(somecondition)map.remove(it.next());
//}
//
//由于对象本身的API只会修改对象自己,而不回去更新迭代器,所以迭代器依然会迭代这个被删除的元素,那么就会抛出ConcurrentModificationException异常了。
//
//以上方法可以保证在同一个线程里迭代器的安全使用,但是,在多线程的环境下,即使你使用迭代器的API去修改对象,或者你根本就没有去修改对象,你也不能保证在你迭代的过程中,其他的线程没有去修改这个对象。那么唯一的方法,就是当一个线程在迭代的过程中,把这个对象锁住,使其它的线程无法对这个对象就行修改。这个时候我们就需要用到Java的同步机制了。我们应该:
//
//
//synchronized(map) {
//Iterator it = map.keySet().iterator();
//while(it.hasNext()) {
//……
//}
//}
//
//由于synchronized关键字是完全锁住一个对象,不论是读还是写。如果想提高性能,在迭代过程中允许读的话,那么就需要用到concurrent.jar包了,创建一个写锁来替换synchronized。

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -