chapt2 java並行程序基礎
讀完原書第二章,記錄下一些要點
1. 關於線程中斷
public class InterruptThread implements Runnable{
@Override
public void run() {
Thread.currentThread().setName("jeyawn thread");
while (true) {
if(Thread.currentThread().isInterrupted()) {
System.out.println("interrup called");
break;
}
try {
System.out.println("before sleep");
Thread.sleep(1000000000000L);
System.out.println("after sleep");
}
catch (InterruptedException e) {
System.out.println("we have excetion:");
if(Thread.currentThread().isInterrupted()) {
System.out.println("current thread interrupted.....");
}
Thread.currentThread().interrupt();
}
}
System.out.println("Thread exit.......");
}
}
public static void Test1() {
String name = ManagementFactory.getRuntimeMXBean().getName();
System.out.println(name);
// get pid
String pid = name.split("@")[0];
System.out.println("pid===>"+pid);
Thread t1 = new Thread(new InterruptThread());
t1.start();
try {
Thread.sleep(3000);
}
catch (Exception e) {
e.printStackTrace();
}
t1.interrupt();
}
這裏需要幾個注意點
interrupt 方法可以製造中斷,在線程那邊會收到InterruptedException ,此時中斷標記已經清除,需要繼續Thread.currentThread().interrupt() 設置中斷。
isInterrupted 可以判斷當前線程是否被中斷
2. java 線程查看方法:
獲取當前進程pid的方法:
String name = ManagementFactory.getRuntimeMXBean().getName();
System.out.println(name);
// get pid
String pid = name.split("@")[0];
System.out.println("pid===>"+pid);
通過jstack命令可以查看線程狀態,例如如下: jstack -l pid
C:\Program Files\Java\jdk1.8.0_191\bin>jstack -l 32556
2019-05-01 15:03:08
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.191-b12 mixed mode):
"DestroyJavaVM" #12 prio=5 os_prio=0 tid=0x0000000002f52800 nid=0x5244 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"jeyawn thread" #11 prio=5 os_prio=0 tid=0x0000000019409800 nid=0x6270 waiting on condition [0x000000001a05f000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at com.jeyawn.threadimpl.InterruptThread.run(InterruptThread.java:23)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"Monitor Ctrl-Break" #10 daemon prio=5 os_prio=0 tid=0x0000000019408800 nid=0x7724 runnable [0x0000000019f5f000]
3.volatile 的使用
volatile這個東西只是表示當前修飾的東西是易變的,jvm在使用的時候需要主動刷新,它不能替代鎖,因此也無法保證原子性。實際上,它具有的功能,synchronized都具有,建議以後還是用synchronized替代volatile。
這裏還引出來一個全局變量共享訪問的事情:
不要簡單的用全局變量(除非加volatile)來作爲兩個線程的通信,也許永遠不會奏效。
public class NoVisibility {
private static int number;
private static boolean ready;
private static class ReaderThread extends Thread {
@Override
public void run() {
int i = 0;
while (!ready) {
i++;
// if(i%100000000 == 0) {
// System.out.println("ready==>"+ready);
// }
}
System.out.println("number:"+number);
}
}
public static void doTest() throws InterruptedException {
new ReaderThread().start();
Thread.sleep(1000L);
number = 1000;
ready = true;
Thread.sleep(10000);
}
}
上面這段代碼在ready沒有用volatile修飾的時候,reader線程沒法看到ready變成true的這個動作,所以永遠不會退出循環(我在jdk9,client模式試的)。但是獎賞一些打印之後(就是被註釋掉的代碼),這塊的代碼又能看到ready變成true這個情況,所以說,對於這樣的情況需要很小心!!!!
4. 其它
非線程安全的數據結構 ArrayList, HashMap
線程安全:Vector, ConcurrentHashMap,CopyOnWriteArrayList(比Vector效率高)