消费者对象:消费队列、消费者ID、消费线程、线程终止标记、线程中断锁
在操作集合方面,如果某一个集合会被多个线程调用就要加锁
package exercise;
import java.util.Vector;
abstract public class Consumer {
private Vector<Object> _queue = new Vector<Object>();
private Object _waitForMonitor = new Object();//用来等待队列的信号
private Thread _thread;//消费者用来消费的单线程
private String _name;//用来标识消费者
private boolean _isTerminated;//用来中止线程的标记
public Thread getThread(){
if(_thread == null){
_thread = new Thread(){
public void run(){
Consumer.this.run();
}
};
}
return _thread;
}
//这个run方法在另外一个线程上跑
private void run(){
goToStart();
while(!_isTerminated){
//这个循环用来从队列中不断地拿出任务,只要队列不空就不会跳出
while(true){
Object o;
synchronized(_queue){
if(_queue.isEmpty())
break;
o = _queue.get(0);
_queue.remove(0);
}
if(o == null)
break;
try{
onConsume(o);
}catch(Exception e){
e.printStackTrace();
}
}
//如果队列为空,准备等待队列不为空,首先要获得这个对象锁,然后还需要判断现在队列是否为空,因为在获得锁之前可能已经有任务插入队列中了。
synchronized(_waitForMonitor){
if(_isTerminated)
break;
if(_queue.isEmpty()){
try{
goToRest();
//此时仍然没有任务,则在wait这个对象锁
_waitForMonitor.wait();
goToWakeUp();
}catch(InterruptedException e){
}
}
}
}
goToTerminate();
}
private void goToTerminate(){
System.out.println(_name + "is go to terminate");
}
private void goToRest(){
System.out.println(_name + "is go to rest");
}
private void goToStart(){
System.out.println(_name + "is beginning");
}
private void goToWakeUp(){
System.out.println(_name + "is go to wake up");
}
private void kickThread(){
//测试线程是否已经中断
if(!getThread().isInterrupted()){
synchronized(_waitForMonitor){
_waitForMonitor.notify();
}
}
}
public Consumer init(String name){
_name = name;
getThread().setName(name+"Consumer");
getThread().start();
return this;
}
public void terminateSelf(){
_isTerminated = true;
kickThread();
}
public void addObject(Object o){
_queue.add(o);
kickThread();
}
public void addObjectWithoutWakeup(Object o){
_queue.add(o);
//kickThread();
}
abstract protected void onConsume(Object input);
public static void main(String[] argv){
//使用了一个匿名内部类来继承 Consumer 类,并重载抽象方法 onConsume()
Consumer consumer = new Consumer(){
protected void onConsume(Object o){
Integer i = (Integer)o;
System.out.println(">>>>"+i);
}
}.init("MyConsumer");
for(int i=1;i<=5;i++)
consumer.addObjectWithoutWakeup(new Integer(i));
for(int i=1;i<=5;i++){
consumer.addObject(new Integer(i));
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
consumer.terminateSelf();
}
}