多線程交替打印AB或者字符串,生產者消費者,死鎖等例子

 

目錄

使用wait和notify實現生產者消費者

使用阻塞隊列來實現生產者消費者模式 

兩線程交替打印AB

簡單死鎖例子

這個也是交替打印AB

交替打印字符串,例如:hello world


 使用wait和notify實現生產者消費者

public class Main2 {
    public static void main(String[] args) {
        LinkedList<Integer> list = new LinkedList<>();
        int MAX = 5;//生產商品總數
        Thread t1 = new Thread(){
            public void run(){
                while ( true ) {
                    synchronized (list) {//加鎖
                        while ( list.size() == MAX ) {
                            try {
                                list.wait();//如果生產商品數目大於生產商品最大值,那麼釋放鎖
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        int num = (int) (Math.random() * 100);
                        list.add(num);
                        System.out.println(Thread.currentThread().getName() + "---" + num);
                        list.notify();//喚醒消費者線程,只有當前線程釋放鎖後才能被喚醒
                    }
                }

            }
        };
        Thread t2 = new Thread(){
            public void run(){
                while ( true ) {
                    synchronized (list) {//加鎖
                        while ( list.size() == 0 ) {//消費完隊列中商品進行等待
                            try {
                                list.wait();//等待釋放鎖
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        int num = list.pop();//隊列中有商品,進行消費
                        System.out.println(Thread.currentThread().getName() + "---" + num);
                        list.notify();//喚醒生產者線程,只有當前線程釋放鎖後才能被喚醒
                    }
                }
            }
        };
        t1.start();
        t2.start();
    }
}

使用阻塞隊列來實現生產者消費者模式 

import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;

/**
 * Created by Hollake on 2019\8\14 0014 15:31.
 */
public class BlockingQueueTest {
    public static void main(String[] args) {
        BlockingDeque<Integer> queue = new LinkedBlockingDeque<>(5);
        Thread t1 = new Thread(){
            public void run(){
                while ( true ) {
                    int temp = (int) (Math.random() * 100);
                    try {
                        queue.put(temp);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "----" + temp);
                }
            }
        };
        Thread t2 = new Thread(){
            public void run(){
                while ( true ) {
                    try {
                        int res = queue.take();
                        System.out.println(Thread.currentThread().getName() + "----" + res);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        t1.start();
        t2.start();
    }
}

 

兩線程交替打印AB

public class Main2 {
    static boolean flag = false;
    public static void main(String[] args) {
        Object LOCK = new Object();
        Thread t1 = new Thread(){
            public void run(){
                while ( true ) {
                    synchronized (LOCK) {//加鎖
                        while ( flag ) {
                            try {
                                LOCK.wait();//滿足條件就釋放鎖
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        System.out.println(Thread.currentThread().getName() + "---" + "A");
                        flag = true;
                        LOCK.notify();//喚醒另外一個線程,只有當前線程釋放鎖後才能被喚醒
                    }
                }

            }
        };
        Thread t2 = new Thread(){
            public void run(){
                while ( true ) {
                    synchronized (LOCK) {//加鎖
                        while ( !flag ) {
                            try {
                                LOCK.wait();//等待釋放鎖
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        System.out.println(Thread.currentThread().getName() + "---" + "B");
                        flag = false;
                        LOCK.notify();//喚醒生產者線程,只有當前線程釋放鎖後才能被喚醒
                    }
                }
            }
        };
        t1.start();
        t2.start();
    }
}

簡單死鎖例子

package arithmetic;

/**
 * Created by Hollake on 2019\7\17 0017 22:08.
 */
public class Main2 {
    static boolean flag = false;
    public static void main(String[] args) {
        Object a = new Object();
        Object b = new Object();
        Thread t1 = new Thread(){
            public void run(){
                synchronized (a) {//加鎖
                    try {
                        Thread.sleep(20);//必須進行睡眠等待,不睡眠等待可以,但是一般不會發生死鎖,因爲程序執行太快
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (b) {//拿到a鎖的情況下還想拿到b鎖,這與另外一個線程情況正好相反,
                        // 持有資源,不釋放資源,還需要其他線程持有的資源,死鎖的條件
                        System.out.println("不會執行到這裏");
                    }
                }
            }
        };
        Thread t2 = new Thread(){
            public void run(){
                synchronized (b) {//加鎖
                    try {
                        Thread.sleep(20);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (a) {
                        System.out.println("不會執行到這裏");
                    }
                }
            }
        };
        t1.start();
        t2.start();
    }
}

這個也是交替打印AB

package arithmetic;

import java.util.LinkedList;

/**
 * Created by Hollake on 2019\6\24 0024 20:41.
 */
public class SwapPrint {
    public static void main(String[] args) throws InterruptedException {
        LinkedList<String> list = new LinkedList<>();
        list.add("A");
        list.add("B");
        list.add("A");
        list.add("B");
        Object a = new Object();
        Object b = new Object();
        MyThread myThread1 = new MyThread(b,a,list);
        MyThread myThread2 = new MyThread(a,b,list);
        (new Thread(myThread1)).start();
        Thread.sleep(100);
        (new Thread(myThread2)).start();

    }
}

class MyThread implements Runnable {
    private LinkedList<String> list;
    private Object pre;
    private Object self;

    public MyThread( Object pre, Object self,LinkedList<String> list) {
        this.self = self;
        this.pre = pre;
        this.list = list;
    }

    @Override
    public void run() {
        while ( !list.isEmpty() ){
            synchronized (pre) {//先拿到前一個線程的鎖
                synchronized (self) {//接着拿到自己的鎖
                    System.out.println(Thread.currentThread() + list.poll());
                    self.notify();//喚醒另外一個線程
                }
                try {
                    pre.wait();//釋放前一個線程的鎖,中止當前線程
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }
    }
}

交替打印字符串,例如:hello world

import java.util.LinkedList;

/**
 * Created by Hollake on 2019\7\17 0017 22:08.
 */
public class Main2 {
    static boolean flag = false;
    static String str = "HELLO WORLD";
    static int max = str.length();
    public static void main(String[] args) {
        Object LOCK = new Object();
        LinkedList<String> list = new LinkedList<>();

        for (int i = 0; i < max; i++) {
            list.add(String.valueOf(str.charAt(i)));
        }
        Thread t1 = new Thread(){
            public void run(){
                while ( max > 0 ) {
                    synchronized (list) {//加鎖
                        while ( flag ) {
                            try {
                                list.wait();//滿足條件就釋放鎖
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        //在這裏爲什兒要進行list是否爲null的判斷呢,仔細思考一下,如果不判斷,例如打印兩個字母ab,
                        // 第一次線程t1打印a後,繼續到try中,調用list.wait()方法,釋放鎖,線程t2拿到鎖,繼續打印b,
                        // 接着同樣的釋放鎖,線程t1從try中的wait()方法中被喚醒,繼續執行,但是list中已經沒有了元素,
                        // 所以調用pop()方法直接會拋出空指針異常
                        if (list.size() > 0) {
                            System.out.println(Thread.currentThread().getName() + "---" + list.pop());
                        }
                        max--;
                        flag = true;
                        list.notify();//喚醒t2線程,只有當前線程釋放鎖後才能被喚醒
                    }
                }

            }
        };
        Thread t2 = new Thread(){
            public void run(){
                while ( max > 0 ) {
                    synchronized (list) {//加鎖
                        while ( !flag ) {
                            try {
                                list.wait();//釋放鎖等待被喚醒
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        if (list.size() > 0) {
                            System.out.println(Thread.currentThread().getName() + "---" + list.pop());
                        }
                        max--;
                        flag = false;
                        list.notify();//喚醒t1線程,只有當前線程釋放鎖後才能被喚醒
                    }
                }
            }
        };
        t1.start();
        t2.start();
    }
}

 

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