`

java解惑(Map的使用,静态导入方法,线程中断interrupted与线程死锁)

阅读更多
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线程的运行结束。因为这两个线程现在正相互等待,形成了
死锁
分享到:
评论

相关推荐

    java线程中的interrupt,isInterrupt,interrupted方法

    java线程中的interrupt,isInterrupt,interrupted方法

    JAVA多线程之中断机制stop()、interrupted()、isInterrupted()

    主要介绍了JAVA多线程之中断机制stop()、interrupted()、isInterrupted()的相关资料,需要的朋友可以参考下

    线程中断的方法以及静态方法isInterrupted和实例方法interrupted的区别

    线程中断 常见的有以下两种方式: 通过共享的标记来进行沟通 调用 interrupt() 方法来通知 通过共享的标记来实现中断 就是创建一个boolean类型的变量来控制循环是否进行,就是一个标记。 代码如下: /** * 描述:...

    Java中interrupt的使用.docx

    中断在java中主要有3个方法,interrupt(),isInterrupted()和interrupted()。 interrupt(),在一个线程中调用另一个线程的interrupt()方法,即会向那个线程发出信号——线程中断状态已被设置。至于那个线程何去何从...

    Java多线程教程吐血整理干货.md

    interrupt,interrupted,isInterrupted方法区别 join方法 yield方法 多线程 进程和线程 进程与线程最主要的区别是它们是操作系统管理资源的不同方式的体现。 准确来说进程与线程属于衍生关系。 进程是操作系统执行...

    Java中断一个线程操作示例

    主要介绍了Java中断一个线程操作,结合实例形式分析了java中断线程相关的interrupt()、isInterrupted()及interrupted()函数使用技巧,需要的朋友可以参考下

    Java解惑(谜题)CHM中英文双版本

    Java谜题 Java谜题1——表达式谜题 谜题1:奇数性 谜题2:找零时刻 谜题3:长整除 谜题4:初级问题 谜题5:十六进制的趣事 谜题6:多重转型 谜题7:互换内容 谜题8:Dos Equis 谜题9:半斤 谜题10:八两 ...

    Java期末复习||应用程序设计-多线程和泛型

    容我多说几句,让更多的人看到我的资源! Java应用程序设计之多线程和泛型 Thread、Runnable、Callable ...同步与死锁、Object类对线程的支持 泛型、通配符、受限泛型、泛型接口、泛型方法、泛型数字、泛型嵌套

    java8源码-JavaSE-Code:JavaSE的代码练习与学习笔记总结

    interrupted是Thread类的静态方法,里面调用了isTnterrupted方法[currentThread().isInterrupted()],测试当前线程是否已经中断,线程的中断状态由该方法清除 isInterrupted是Thread类的实例方法,不清除中断标志 yield...

    JUC学习.docx Java

    (2)使用FutureTask(实现Runnable接口)来指定任务,可以通过get方法来获得执行结果,如果当前还获取不到结果就会阻塞,直到结果返回。 (3)调用start方法只是让线程进入就绪状态,是否可以真正运行run()是由任务调度器...

    线程问题解决线程问题解决线程问题解决

    线程问题解决线程问题解决线程问题解决线程问题解决线程问题解决

    Thread类的interrupt(),interrupted(),isInterrupted()1

    一般来说,支持线程中断的方法(也就是线程中断后会抛出InterruptedException的方法),阻塞函数,如:Thread.sleep、Thread.jo

    oracle连接失败

    oracle连接失败 解决方案 超详细 挺有用的

    java线程池概念.txt

    线程安全,并发的知识有加深认知;当然,现在用过的东西并不是代表以后还能娴熟的使用,做好笔记非常重要; 1:必须明白为什么要使用线程池:(这点很重要)  a:手上项目所需,因为项目主要的目的是实现多线程的...

    Linux下semop等待信号时出现Interrupted System Call错误(EINTR)解决方法

    错误现象:(semop函数调用,strerror(errno)输出结果)Interrupted system call平台:RedHat LinuxLINUX文档关于EINTR的描述是这样子的: While blocked in this system call, the process caught a signal.UNIX文档...

    keyboard按键中断驱动

    ########## # README # ########## Purpose ------- To help understand which is the most commonly 'pressed' and 'released' key in the keyboard....of pressing need not be equal to release count....

    Su04_Concurrency:类中并发主题的代码示例

    InterruptedThread:这是一个示例,说明如何可以中断另一个线程并捕获Interrupted Exception。 死锁:死锁的简单示例。 no03_parallelworkers:启动将启动多个Worker。 可视化多个线程之间的切换。 no03_...

    OSError:[Errno 4]Interrupted system call

    OSError:[Errno 4]Interrupted system call 问题描述: File “/anaconda2/python2.7/multiprocessing/reduction.py”, line 157, in rebuild_handle new_handle = recv_handle(conn) File “/anaconda2/python2.7/...

    出现IE脚本错误

    解决ntbst启动有弹出框.reg

Global site tag (gtag.js) - Google Analytics