多线程交替打印AB或者字符串,生产者消费者,死锁等例子

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/Hollake/article/details/93529701

 

目录

使用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();
    }
}

猜你喜欢

转载自blog.csdn.net/Hollake/article/details/93529701
今日推荐