java多线程学习:
生产者和消费者
问题:
Cannot refer to a non-final variable file inside an inner class defined in a different method
如果定义一个局部内部类,并且局部内部类使用了一个在其外部定义的对象,为什么编译器会要求其参数引用是final呢?
注意:局部内部类,包括匿名内部类。
自己写的生产和消费者的类遇到的问题,  final Goods pru  = new Goods();
没有在Goods 前加final,里面	pru.produce(str) ;
始终报错Cannot refer to a non-final variable file inside an inner class defined in a different method
Thread thread1 = new Thread(new Runnable(){
	 	public	void run(){
				while(pru.num<=20){
				pru.produce(str) ;
				
			}
		}
package test;
public class PruConsumer {
	/**
	 * @param args生产者和消费者的游戏
	 * @author zhuyh
	 */
	public static void main(String[] args) {
	class Goods{
	 private  int num;
	 private  String name;
	 private boolean flags =false;
	 
	public  synchronized void produce(  String  name){
		while(flags){
		try{
			
			wait();
			
		}catch(InterruptedException e){
				e.printStackTrace();
			
		}
		}
		this.name = name+"--编号" + num++;
		 System.out.println(Thread.currentThread().toString() +" 生产了:" +this.name);		
		 flags= true;
			notifyAll(); 
	 }
	
	
	public  synchronized void consumer(){
		while(!flags){
		try{
			
			wait();
			
		}catch(InterruptedException e){
				e.printStackTrace();
			
		}
		}
		 System.out.println(Thread.currentThread().toString() +" :消费了:" +this.name);		 
		 flags= false;
			notifyAll(); 
	 }
	
	}
		// TODO Auto-generated method stub
	  final Goods pru  = new Goods();
		final String str="商品";
		Thread thread1 = new Thread(new Runnable(){
	 	public	void run(){
				while(pru.num<=20){
				pru.produce(str) ;
				
			}
		}
		
		
			
		},"生产者一号");
		thread1.start();
		
		Thread thread2 = new Thread(new Runnable(){
		 	public	void run(){
					while(pru.num<=20){
					pru.produce(str) ;
					
				}
			}		
			},"生产者二号");
			thread2.start();
			
			Thread thread3 = new Thread(new Runnable(){
			 	public	void run(){
						while(pru.num<=20){
							pru.consumer();
						
					}
				}		
				},"消费者一号");
				thread3.start();
				
				Thread thread4 = new Thread(new Runnable(){
				 	public	void run(){
							while(pru.num<=20){
								pru.consumer();
							
						}
					}		
					},"消费者二号");
					thread4.start();			
				
			
	}
}
网上找到解释
JVM中每个进程都会有多个根,每个static变量,方法参数,局部变量,当然这都是指引用类型.基础类型是不能作为根的,根其实就是一个存储地址.垃圾回收器在工作时先从根开始遍历它引用的对象并标记它们,如此递归到最末梢,所有根都遍历后,没有被标记到的对象说明没有被引用,那么就是可以被回收的对象(有些对象有finalized方法,虽然没有引用,但JVM中有一个专门的队列引用它们直到finalized方法被执行后才从该队列中移除成为真正没有引用的对象,可以回收,这个与本主题讨论的无关,包括代的划分等以后再说明).这看起来很好但是在内部类的回调方法中,s既不可能是静态变量,也不是方法中的临时变量,也不是方法参数,它不可能作为根,在内部类中也没有变量引用它,它的根在内部类外部的那个方法中,如果这时外面变量s重指向其它对象,则回调方法中的这个对象s就失去了引用,可能被回收,而由于内部类回调方法大多数在其它线程中执行,可能还要在回收后还会继续访问它.这将是什么结果?而使用final修饰符不仅会保持对象的引用不会改变,而且编译器还会持续维护这个对象在回调方法中的生命周期.所以这才是final变量和final参数的根本意义.
Cannot refer to a non-final variable file inside an inner class defined in a different method
原文:http://www.cnblogs.com/yaiping/p/5216655.html