實戰java高併發程序設計學習(1)

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效率高)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章