线程间通信Demo

一 实现生产者/消费者两个线程交替执行

我们以生产面包线程  和 消费面包线程做例子

面包类
public class Bread {
    //面包个数
    private  int num;
    //面包id
    private  int id;

    //生产面包
    public  synchronized void creat(){
        //面包不等于0 等待
        if(num!=0){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //数量等于 0 生产面包
        num++;
        id++;
        System.out.println(Thread.currentThread().getName()+"生产了 id为"+id+"的面包");
        notify();//唤醒消费面包的线程
    }

    public  synchronized  void consume(){
        if(num==0){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //有面包了  被唤醒
        //开始消费面包
        num--;
        System.out.println(Thread.currentThread().getName()+"消费了 id为"+id+"的面包");
        notify();//面包没有了 唤醒生产面包的线程
    }
}

 

消费者

public class Consumer extends Thread{

    private  Bread bread;

    public Consumer(Bread bread) {
        this.bread = bread;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            this.bread.consume();
        }
    }
}

生产者

public class Creater extends Thread {
    private Bread bread;

    public Creater(Bread bread) {
        this.bread = bread;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            this.bread.creat();
        }
    }
}

测试

public class TestBread {
    public static  void main(String[] args){
        Bread bread = new Bread();
        Consumer consumer = new Consumer(bread);
        Creater creater = new Creater(bread);

      consumer.start();
      creater.start();

    }
}

结果:

Thread-1生产了 id为1的面包
Thread-0消费了 id为1的面包
------省略-------
Thread-1生产了 id为20的面包
Thread-0消费了 id为20的面包

知识点:

1.synchronized修饰方法锁住的是对象的本身,也是this。谁调用的方法,锁住的就是那个对象。(main方法创建的bread对象)

2.wait,notify,notifyAll方法:

  作用导致线程进人等待状态直到它被通知。随机选择一个在该对象上调用 wait 方法的线程, 解除其阻塞状态。解除那些在该对象上调用 wait 方法的线程的阻塞状态。

 注意:必须在同步代码块,或者是同步方法和cock和unlcok方法中间调用。

分析:在上述例子中,两个synchronized方法锁住的是同一个bread对象(同一对象锁),因此wait和notify注册在同一个对象锁上。

 

二     三线程交替顺序执行

1.notify/wait方法

public class Test1 {
    private  static  Object object = new Object();
    private static int count = 0;

    static  Thread A = new Thread(new Runnable() {
        @Override
        public void run() {
            while (true){
                synchronized (object){
                    if(count%3==0){
                        System.out.println("Thread A is run");
                        count++;
                        object.notifyAll();
                    }else {
                        try {
                            object.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    });

    static Thread B = new Thread(new Runnable() {
        @Override
        public void run() {
            while (true){
                synchronized (object){
                    if(count%3==1){
                        System.out.println("Thread B is run");
                        count++;
                        object.notifyAll();
                    }else {
                        try {
                            object.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    });

    static  Thread C = new Thread(new Runnable() {
        @Override
        public void run() {
            while (true){
                synchronized (object){
                    if(count%3==2){
                        System.out.println("Thread C is run");
                        count++;
                        object.notifyAll();
                    }else {
                        try {
                            object.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    });

    public  static  void  main(String[] args){
        long t1 = System.currentTimeMillis();
        A.start();
        B.start();
        C.start();
        while (true) {
            if (System.currentTimeMillis() - t1 > 5) {
                System.exit(0);
            }
        }
    }
}

2.使用Lock与Condition


public class Test2 {
    private static Lock lock = new ReentrantLock();
    private static int count = 0;
    static Condition c1 = lock.newCondition();
    static   Condition c2 = lock.newCondition();
    static Condition c3 = lock.newCondition();

   static Thread  A = new Thread(new Runnable(){
        @Override
        public void run() {
            while (true) {
                lock.lock();
                try {
                while (count % 3 != 0) {
                    c1.await();
                }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println("Thread A is run:"+System.currentTimeMillis());
                    count++;
                    c2.signal();

                lock.unlock();

            }
        }
    });

    static Thread  B  = new Thread(new Runnable(){
        @Override
        public void run() {
            while (true) {
                lock.lock();
                try {
                    while (count % 3 != 1) {
                        c2.await();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println("Thread B is run:"+System.currentTimeMillis());
                count++;
                c3.signal();

                lock.unlock();

            }
        }
    });

    static Thread  C = new Thread(new Runnable(){
        @Override
        public void run() {
            while (true) {
                lock.lock();
                try {
                    while (count % 3 != 2) {
                        c3.await();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println("Thread C is run:"+System.currentTimeMillis());
                count++;
                c1.signal();

                lock.unlock();

            }
        }
    });

    public  static void  main(String[] a){
        long t1 = System.currentTimeMillis();
        A.start();
        B.start();
        C.start();
        while (true){
            if(System.currentTimeMillis()-t1>10){
                System.exit(0);
            }
        }
    }
}

 

3 使用信号量Semaphore


public class ConcurrentPrint {
    // 共享资源个数都初始为1
    private static Semaphore s1 = new Semaphore(1);
    private static Semaphore s2 = new Semaphore(1);
    private static Semaphore s3 = new Semaphore(1);
    Thread t1 = new Thread(new Runnable() {
        public void run() {
            while (true) {
                try {
                    s1.acquire();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println("A");
                s2.release();
            }
        }
    });
    Thread t2 = new Thread(new Runnable() {
        public void run() {
            while (true) {
                try {
                    s2.acquire();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println("B");
                s3.release();
            }
        }
    });
    Thread t3 = new Thread(new Runnable() {
        public void run() {
            while (true) {
                try {
                    s3.acquire();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println("C");
                s1.release();
            }
        }
    });
 
    public void fun() throws InterruptedException {
        // 先占有输出BC的线程的信号量计数
        // 则只能从输出A的线程开始。获取信号量A,然后释放B-获取B-释放C-获取C-释放A,由此形成循环
        s2.acquire();
        s3.acquire();
        t2.start();
        t3.start();
        t1.start();
    }
 
    public static void main(String[] args) throws InterruptedException {
        ConcurrentPrint cp = new ConcurrentPrint();
        long t1 = System.currentTimeMillis();
        cp.fun();
        while (true) {
            if (System.currentTimeMillis() - t1 >= 10)
                System.exit(0);
        }
    }
}

原文:

https://blog.csdn.net/qq_26567507/article/details/82666852

https://www.cnblogs.com/Wenxu/p/7979023.html

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