Map的使用
package other;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;
class T {
private String str;
T(String str) {
this.str = str;
}
public int hashCode() {
return 37 * this.str.hashCode();
}
public boolean equals(Object obj) {
return this.str.equals(((T) obj).str);
}
public static void put(Map m) {
m.put("str", "1");
/*
* 由于上面程序将 "str" 放入了字符串常量池,
* 所以str是同一个对象,不管是什么样类型的
* Map,即使使用IdentityHashMap都只放入一次
*/
m.put("str", "2");
m.put(new T("str"), "3");
m.put(new T("str"), "4"); //这两个T如果用equals比较,相等,所以放入map中,后者替换前者,如果没有重写Object的equals方法,则视为不同
}
public static void main(String[] args) {
Map m = new HashMap();
put(m);
System.out.println("map的大小为:"+m.size());// 2
for(Object key:m.keySet()){
System.out.println(m.get(key));//2,4
}
//IdentityHashMap比较时使用==替换equals()方法
m = new IdentityHashMap();
put(m);
System.out.println("使用IdentityHashMap,map的大小为:"+m.size());// 3
for(Object key:m.keySet()){
System.out.println(m.get(key));//3,2,4或4,3,2等,map是无序的,即添加数据的顺序和取出数据顺序可能不同
}
}
}
注意:
IdentityHashMap此类利用哈希表实现 Map 接口,比较键(和值)时使用引用相等性代替对象相等性。换句话说,在 IdentityHashMap 中,当且仅当 (k1==k2) 时,才认为两个键 k1 和 k2 相等
2,静态导入方法
package ch7;
import static java.util.Arrays.toString;
import java.util.Arrays;
public class T {
public static void main(String[] args) {
prt(1, 2, 3);
}
static void prt(Object... args) {
// 自身继承至Object类的toString的优先级高于静态导入的方法
// System.out.println(toString(args));//不能编译,Object类中的toString方法没有参数,所以出现compile error
System.out.println(Arrays.toString(args)); //[1,2,3]
}
}
System类中的字段有:
static PrintStream err
“标准”错误输出流。
static InputStream in
“标准”输入流。
static PrintStream out
“标准”输出流。
java.lang.Object
java.io.OutputStream
java.io.FilterOutputStream
java.io.PrintStream
package ch7;
import static java.util.Arrays.toString;
import java.util.Arrays;
public class T {
public static void main(String[] args) {
prt(1, 2, 3);
String str = "Hello World";
for (int i = 0; i < str.length(); i++) { //不会输出
System.out.write(str.charAt(i));
}
System.out.flush(); //刷新缓冲区才会输出out流中的数据?????????
}
}
3,线程的中断Thread.interrupted
thread. isInterrupted()与Thread.interrupted()
public class SelfInerruption {
public static void main(String[] args) {
Thread.currentThread().interrupt();
if (Thread.interrupted()) {
// Interruped:false
System.out.println("Interruped:" + Thread.interrupted());
} else {
System.out.println("Not interruped:" + Thread.interrupted());
}
}
}
Thread.interrupted()为Thread的静态方法,调用它首先会返回当前线程的中断状态(如果当前线程上调用了interrupt()方法,则返回true,否则为false),然后再清除当前线程的中断状态,即将中断状态设置为false。换句话说,如果连续两次调用该方法,则第二次调用将返回 false。而isInterrupted()方法为实例方法,测试线程是否已经中断,并不会清除当前线程中断状态。
所以这里应该使用isInterrupted()实例方法,就可以修复该问题。
package other;
public class SelfInerruption {
public static void main(String[] args) {
Thread t = Thread.currentThread();
System.out.println(t.getName()); //main
t.interrupt(); //中断
if (t.interrupted()) { // 是静态方法,建议不要这么调用,当前线程被中断,所以为true
System.out.println("Interruped:" + t.interrupted()); //Interruped:false,再次调用interrupted(),返回为false
} else {
System.out.println("Not interruped:" + t.interrupted());
}
}
}
线程问题
package other;
//类的初始化,先初始化静态域,静态块,
public class Lazy {
private static boolean initial = false;
static {
Thread t = new Thread(new Runnable() {
public void run() {
System.out.println("befor...");//此句会输出
/*
* 由于使用Lazy.initial静态成员,又因为Lazy还未 初
* 始化完成,所以该线程会在这里等待主线程初始化完成
*/
initial = true;
System.out.println("after...");//此句不会输出
}
});
t.start();
try {
t.join();// 主线程等待t线程结束
} catch (InterruptedException e) {
e.printStackTrace();
}
}//static
public static void main(String[] args) {
System.out.println(initial);
}
}
执行结果就是:befor...
当一个线程访问一个类的某个成员的时候,它会去检查这个类是否已经被初始化,在这一过程中会有以下四种情况:
1、 这个类尚未被初始化
2、 这个类正在被当前线程初始化:这是对初始化的递归请求,会直接忽略掉(另,请参考《构造器中静态常量的引用问题》一节)
3、 这个类正在被其他线程而不是当前线程初始化:需等待其他线程初始化完成再使用类的Class对象,而不会两个线程都会去初始化一遍(如果这样,那不类会初始化两遍,这显示不合理)
4、 这个类已经被初始化
当主线程调用Lazy.main,它会检查Lazy类是否已经被初始化。此时它并没有被初始化(情况1),所以主线程会记录下当前正在进行的初始化,并开始对这个类进行初始化。这个过程是:主线程会将initial的值设为false,然后在静态块中创建并启动一个初始化initial的线程t,该线程的run方法会将initial设为true,然后主线程会等待t线程执行完毕,此时,问题就来了。
由于t线程将Lazy.initial设为true之前,它也会去检查Lazy类是否已经被初始化。这时,这个类正在被另外一个线程(main线程)进行初始化(情况3)。在这种情况下,当前线程,也就是t线程,会等待Class对象直到初始化完成,可惜的是,那个正在进行初始化工作的main线程,也正在等待t线程的运行结束。因为这两个线程现在正相互等待,形成了
死锁。