Java三个线程循环打印

版权声明:作者: 阿顾, 转载请写明出处, 谢谢 https://blog.csdn.net/u010452388/article/details/82777908

先上效果图: 

 

目录

资源

测试


资源

这里用了condition

执行流程:线程1执行完,让线程2醒来工作;线程2执行完,让线程3醒来工作;线程3执行完,让线程1醒来工作

原理(都是按最坏的情况分析):

①一开始3个线程抢锁,如果线程2和3抢到锁,会进入等待(因为num=1),并释放锁,此时只有线程1可以拿锁

②线程1开始执行,将num=2,并唤醒线程2,此时线程1和线程2竞争锁,如果线程1抢到锁,会进入等待,并释放锁,此时只有线程2可以拿锁

③线程2开始执行,将num=3,并唤醒线程3,此时线程2和线程3竞争锁,如果线程2抢到锁,会进入等待,并释放锁,此时只有线程3可以拿锁

④线程3开始执行,将num=1,并唤醒线程1,此时线程3和线程1竞争锁,如果线程3抢到锁,会进入等待,并释放锁,此时只有线程1可以拿锁

这样就能保证三个线程循环执行了


import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Resource {
    //num=1就是线程1执行,num=2就是线程2执行,num=3就是线程3执行
    private int num = 1;
    private Lock lock = new ReentrantLock();//创建锁对象
    private Condition condition1 = lock.newCondition();//条件1
    private Condition condition2 = lock.newCondition();//条件2
    private Condition condition3 = lock.newCondition();//条件3


    public void sub1() {
        try {
            lock.lock();//开启锁
            while (num != 1){//这里jdk源码里推荐用while,因为有可能出现虚假唤醒,所以要再次确认
                try {
                    condition1.await();//条件1线程等待,并释放锁
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //运行到这里,说明num=1
            num=2;
            Thread.sleep(1000);
            System.out.println("线程1运行完毕");
            condition2.signal();//唤醒条件2线程
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();//释放锁
        }

    }


    public void sub2() {
        try {
            lock.lock();//开启锁
            while (num !=2) {//这里jdk源码里推荐用while,因为有可能出现虚假唤醒,所以要再次确认
                try {
                    condition2.await();//条件2线程等待,并释放锁
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //如果线程执行到这里,说明num=2
            num=3;
            Thread.sleep(1000);
            System.out.println("线程2运行完毕");
            condition3.signal();//唤醒条件3线程
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();//释放锁
        }

    }

    public void sub3() {
        try {
            lock.lock();//开启锁
            while (num !=3) {//这里jdk源码里推荐用while,因为有可能出现虚假唤醒,所以要再次确认
                try {
                    condition3.await();//条件3线程等待,并释放锁
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //如果线程执行到这里,说明num=3
            num=1;
            Thread.sleep(1000);
            System.out.println("线程3运行完毕");
            condition1.signal();//唤醒条件1线程
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();//释放锁
        }

    }
}

测试

public static void main(String[] args) {
        Resource resource = new Resource();
        //第一个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    resource.sub1();
                }
            }
        }).start();
        //第二个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    resource.sub2();
                }

            }
        }).start();
        //第三个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    resource.sub3();
                }

            }
        }).start();
    }

猜你喜欢

转载自blog.csdn.net/u010452388/article/details/82777908