更多库之谜总结

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 } }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值