更多库之谜总结

1.在使用多线程时要注意run方法和start方法的区别

    t.run();main线程调用t的run方法,并没有创建新线程。

    t.start();创建一个新的线程t,并执行。

public class PuzzleDemo76{
	public static synchronized void main(String args[]){	//主线程获得PuzzleDemo76对象的锁
		Thread t = new Thread(){
			public void run(){
				pong();
			}
		};
		t.start();
		System.out.println("ping");
	}
	static synchronized void pong(){	//等待main线程执行完毕,才能够使得t线程获得锁
		System.out.println("pong");
	}
}


2.Thread的join()方法注意点

表示正在被链接的Thread实例调用wait方法,因此会释放锁。

因此如果你需要某个对象的锁的完全控制,则必须确保没有其他线程访问。

import java.util.*;
public class PuzzleDemo77{
	public static void main(String args[])throws Exception{
		final Worker w = new Worker();
		Thread t = new Thread(w);
		t.start();
		Timer timer = new Timer(true);
		timer.schedule(new TimerTask(){
			public void run(){
				w.keepWorking();
			}
		},500);
		Thread.sleep(400);
		w.quit();	//获得w的锁,并执行方法
	}
}
class Worker implements Runnable{
	private volatile boolean quitTime = false;
	public void run(){
		while(!quitTime){
			pretendToWork();
		}
		System.out.println("Beer is good");
	}
	private void pretendToWork(){
		try{
			Thread.sleep(300);
		}
		catch(Exception e){
			
		}
	}
	synchronized void quit() throws Exception{
		quitTime = true;
		Thread.yield();//释放锁
	}
	synchronized void keepWorking(){
		quitTime = true;
	}
}


3.HashSet的问题

HashSet<String>s = new HashSet<String>();

Iterator i = s.iterator();    这里的i是HashMap.keyIterator类型的。但是因为这个类型是不同包中且非公共的,因此不能调用他的方法。

class HashSet{

    private transient HashMap<E,Object> map;

    public Iterator<E> iterator() {
        return map.keySet().iterator();
    }

}

import java.util.*;
import java.lang.reflect.*;
public class PuzzleDemo78{
	public static void main(String args[])throws Exception{
		Set<String> s = new HashSet<String>();
		s.add("foo");
		Iterator iter = s.iterator();
		Method m = Iterator.class.getMethod("hasNext");
		System.out.println(m.invoke(iter));
	}
}


4.编译器寻找调用方法的规则:在正确的名称方法的最内层作用域查找需要调用的方法。


5.Class.newInstance和内部类

Class.newInstance()是调用一个空的构造器。

而非静态内部类调用空构造器时,会有一个隐藏的一个参数即外部类实例,因此外表看起来是空的内部类构造器并不是空构造器。

结论:避免使用反射实例化内部类。

import java.lang.reflect.*;
public class PuzzleDemo80{
	public static void main(String args[])throws Exception{
		new PuzzleDemo80().greetWorld();
	}
	private void greetWorld()throws Exception{
		Constructor c = Inner.class.getConstructor(PuzzleDemo80.class);
		System.out.println(c.newInstance(PuzzleDemo80.this));
	}
	public class Inner{
		public Inner(){}
		public String toString(){
			return "Hellow";
		}
	}
}


6.System.out的一个瑕疵

System.out是一个PrintStream,因此带有缓冲区,但是可以自动刷新。

但是有一个方法例外!

write(int)是唯一一个在自动刷新功能开启的情况下不刷新PrintStream输出流的方法。

public class PuzzleDemo81{
	public static void main(String args[]){
		String greeting = "Hello ";
		for(int i=0;i<greeting.length();i++){
			System.out.println(greeting.charAt(i));
		}
	}
}


7.复制对象的简单方法及解决

实现了io.serializable的类可以简单的通过writeObject和readObject复制对象,并生成一个新的对象。

如果一个类是Singleton,因此只能有一个对象,怎么能够解决这个问题使得通过writeObject和readObject后的对象还是其本身呢?

private Object readResolve(){

    return **;

}

 

import java.io.*;
class Dog extends Exception{
	public static final Dog INSTANCE = new Dog();
	private Dog(){}
	public String toString(){
		return "woof";
	}
	private Object readResolve(){	//实现readResolve方法,使得只有一个实例
		return INSTANCE;
	}
}
public class PuzzleDemo83{
	public static void main(String args[])throws Exception{
		Dog dog = Dog.INSTANCE;
		ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("1.txt"));
		out.writeObject(dog);
		out.close();
		ObjectInputStream in = new ObjectInputStream(new FileInputStream("1.txt"));
		Dog dog2 = (Dog)in.readObject();
		in.close();
		System.out.println(dog==dog2);
	}
}

8.Thread.interrupted()和Thread.isInterrupted()的 区别

Thread.interrupted()方法后会清除当前线程的中断状态。

Thread.isInterrupted()则只是测试是否已经被中断。

 

public class PuzzleDemo84{
	public static void main(String args[]){
		Thread.currentThread().interrupt();
		if(Thread.currentThread().isInterrupted

()){
			System.out.println

("Interrupt:"+Thread.currentThread().isInterrupted());
		}
		else{
			System.out.println(" Not 

Interrupt:"+Thread.currentThread().isInterrupted());
		}
	}
}

9.多线程下的初始化

当一个线程访问一个类的某个成员之前,都会去检查这个类是否已经被初始化。

多线程下类初始化有4种情况:

(1)这个类没被初始化。

(2)这个类被当前线程初始化。

(3)这个类被其他线程初始化。

(4)这个类已经被初始化。

当第三种情况下,如果B线程要访问A类的某个成员,则发现正在被C线程初始化,则会等待C线程初始化完毕,才会继续运行。

结论:要明确初始化顺序。

public class PuzzleDemo85{
	private static boolean initialize = true;		//1
	private static Thread t = new Thread(new Runnable(){	//2
			public void run(){
				initialize = true;
			}
		});
	static{
		System.out.println(initialize);
		t.start();		//3
		
	}
	public static void main(String args[]){
		try{
			System.out.println("main:"+initialize);
			t.join();	//4
		}
		catch(Exception e){}
		System.out.println(initialize);	//5
	}
}

 

 

你可能感兴趣的:(thread,exception,String,iterator,Class,import)