多線程複習(一)

新建線程的方法有三種
1、繼承Thread類
2、繼承runnable接口
3、繼承callable

執行線程的方法有兩種
1、Thread.start();
2、ExcuteService.excute(new Thread);

線程的五種狀態:
1、新建
2、就緒
3、運行
4、阻塞
5、結束

Thread類:

    run()和start()要注意一下,run意味着在當前線程執行了實例的某個方法,start意味着開啓線程,僅僅是run()的話是沒有並行工作的效應的。
    yield()暫停線程,不能指定時間,僅僅是可以讓同優先級的線程先執行。sleep()線程睡眠可以指定睡眠多少時間,可以讓其他線程獲得執行,但是不釋放鎖,信息依然不共享。
    join()等待線程結束,如果在ThreadA中調用threadB.join()則ThreadA的thread.join()後面的程序要等到threadB結束後才運行。是fork-join的主要實現方法。
    get/setPriority()設置優先級

線程同步:

    關鍵字synchronizd,如果某個static方法要鎖,則給整個類加鎖,如果是給某個對象實例的某個代碼塊加鎖,則給對象加鎖。
    感覺最重要的:顯示加鎖以下給出書上的消費生產者實例
public class threadTest {
    private static Buffer buffer = new Buffer();


    public static void main(String[] args) {
        /*建立線程池
        * 線程池用於管理併發執行任務個數的方法
        * newFixed池如果任務超過規定的上線,則新的線程等待之前的任務執行完畢*/
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        executorService.execute(new ProducerTask());
        executorService.execute(new ConsumerTask());
        executorService.shutdown();
    }
    static class ProducerTask implements Runnable{

        @Override
        public void run() {
            try {
                int i=1;
                while (true){
                    System.out.println("Producer writes "+i);
                    buffer.write(i++);
                    Thread.sleep((int)(Math.random()*10000));
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    static class ConsumerTask implements Runnable{

        @Override
        public void run() {
            try {
                while (true){
                    System.out.println("\t\t\tConsumer reads"+buffer.read());
                    Thread.sleep((int)(Math.random()*10000));
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    static class Buffer{
        //定義buffer的大小
        private static final int CAPACITY = 1;
        private LinkedList<Integer> queue = new LinkedList<>();
        //創建一個新lock
        private static Lock lock = new ReentrantLock();
        private static Condition notEmpty = lock.newCondition();
        private static Condition notFull = lock.newCondition();

        public void write(int value){
            lock.lock();
            try {
                while (queue.size()==CAPACITY){
                    //隊列已滿等待未滿的信號來進行解鎖進行下一步插入操作
                    System.out.println("Wait for notFull condition to insert");
                    notFull.await();
                }

                queue.offer(value);
                //當前隊列非空,釋放當前隊列非空信號,使下面的read操作可以執行下去
                notEmpty.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            finally {
                lock.unlock();
            }
        }
        public int read(){
            int value = 0;
            lock.lock();
            try {
                while (queue.isEmpty()){
                    System.out.println("\t\twait for notEmpty condition");
                    notEmpty.await();
                }
                value = queue.remove();
                notFull.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            finally {
                lock.unlock();
                return value;
            }
        }

    }
}

lock和condition:

    lock是鎖住代碼塊的鎖,condition是從lock中獲取的標識,個人暫時理解爲程序阻塞點的標識。
    condition有如下方法:await()讓程序阻塞,signal()喚醒同一個condition實例阻塞的程序,signalAll()喚醒同一個lock的所有condition實例。

Object的線程方法:

    wait,notify,notifyAll,Object自帶的原生方法,這些方法必須在實例的同步方法或者同步代碼塊中調用,具體效果類似於condition裏面的wait和signal

死鎖:

如下`thread1
synchronized(object1){
        synchronized(object2){

        }       
thread2

synchronized(object2){
        synchronized(object1){
        }
    }
    即兩個線程互相等待對方的鎖。
    避免死鎖的方式:採用正確的資源排序避免死鎖.
發佈了43 篇原創文章 · 獲贊 1 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章