併發編程的藝術 -線程基礎

併發編程藝術
二:java 併發編程基礎
程序的正確性不能依賴線程的優先級高低,因爲操作環境可能會忽略線程的優先級。


start()含義:當前線程同步告知java虛擬機,只要線程規劃器空閒,應立即啓動調用start方法的線程。(自定義線程最好起個名字)
中斷:
中斷可以理解爲線程的一個標示位屬性,他表示一個運行中的線程是否唄其他線程進行了中斷操作,
線程通過檢查自身是否唄中斷來進行響應,線程通過isInterrupted來進行判斷是否被中斷。也可以調用靜態方法Thread.interrupted對當前線程的中斷標示位進行復位,
虛擬機先清除中斷標示,再跑出異常。
4.3 線程之間的通信
4.3.1
volatile:確保了一個變量改變會同步到主內存中去,所以其他線程看到的都是最新的。
sychronized:保證了同一時刻只能有一個線程處於同步方法或者同步塊中,保證了線程對變量訪問的可見性和排他性。


4.3.2 等待通知
wait()等待,notify()/notifyAll()通知。


wait/notify/notifyAll使用細節

package com.souche.sts.test;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
* 
* @create: 2019-09-24 08:49
**/
public class WaitNotifyTest {

static boolean flag = true;
static Object lock = new Object();

public static void main(String[] args) throws Exception {
    Thread wait = new Thread(new Wait(),"WaitIng");
    wait.start();
    TimeUnit.SECONDS.sleep(1);
    Thread notify = new Thread(new Notify(),"notifying");
    notify.start();
}



static class Wait implements Runnable {

@Override
public void run() {
    synchronized (lock) {
    while (flag) {
        try {
            System.out.println(Thread.currentThread()+"-1-"+new SimpleDateFormat("HH:mm:ss").format(new Date()));
            lock.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
    }
}
System.out.println(Thread.currentThread()+"-2-"+new SimpleDateFormat("HH:mm:ss").format(new Date()));
        }
    }
}

static class Notify implements Runnable {

@Override
public void run() {
    synchronized (lock) {
        System.out.println(Thread.currentThread()+"-3-"+new SimpleDateFormat("HH:mm:ss").format(new Date()));
        lock.notifyAll();
        flag = false;
        second(5);
}
    synchronized (lock) {
        System.out.println(Thread.currentThread()+"-4-"+new SimpleDateFormat("HH:mm:ss").format(new Date()));
        second(5);
        }
    }
}



public static final void second(long seconds) {
try {
    TimeUnit.SECONDS.sleep(seconds);
} catch (InterruptedException e) {
    e.printStackTrace();
        }
    }
}
結果:
Thread[WaitIng,5,main]-1-09:00:47
Thread[notifying,5,main]-3-09:00:48
Thread[notifying,5,main]-4-09:00:53
Thread[WaitIng,5,main]-2-09:00:58


細節注意:
1:使用這三個方法時需要先加鎖
2:調用wait後,線程狀態由runing變爲waiting,並將當前線程放置到對象等待隊列。
3:調用notify/notifyAll後,等待線程依舊不會從wait返回,需要待用notify的線程釋放鎖之後,才能從等待隊列中返回。
4:從wait返回的前提是獲得了調用對象的鎖。


4.3.4 管道輸入/輸出流
PipedOutputStream,PipedInputStream,PipedReader,PipedWriter,前兩種是字節,後面是字符。
4.3.5 Thread.join()的使用
如果一個線程a執行了thread.join(),含義是:當前線程a等待thread線程終止之後才從thread.join()返回,線程thread除了提供join方法之外,還提供了join(long millis)和join(long millis,int nanos)兩個具備超時特性的方法。
每個線程終止的前提是前驅線程的終止,每個線程等待前驅線程終止後,才從join方法返回。
4.3.6 ThreadLocal的使用
ThreadLocal即線程變量,是一個以ThreadLocal對象爲鍵,任意對象爲值的存儲結構。
4.4 線程應用
4.4.1 等待超時模式
4.4.2 數據庫連接池
例子:https://gitee.com/heqiang917/study/tree/master/src/main/java/com/study/webapp/concurrency_progranmming
線程池的本質就是使用了一個線程安全的工作隊列連接工作者和客戶端,客戶端線程將任務放入工作隊列後返回,而工作者線程則不斷地從工作隊列上取出工作並執行,點那個工作隊列爲空時,所有的工作者線程均等待在工作隊列中,當有客戶端提交了一個任務之後會通知任意一個工作者線程,隨着大量的任務被提交,更多的工作者線程會被喚醒。

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