美文网首页
JAVA并发如何让线程顺序执行

JAVA并发如何让线程顺序执行

作者: 叶子丶恬 | 来源:发表于2020-05-09 00:00 被阅读0次

    方法一

    利用Lock锁中的Condition等待/唤醒机制,让三个线程顺序打印1 ~ N个数值。

    public class ThreadQueueDemo {
        static int count = 1;
        static Lock lock = new ReentrantLock();
        
        /**
         * 定义每个线程对应的condition
         */
        static Condition one = lock.newCondition();
        static Condition two = lock.newCondition();
        static Condition three = lock.newCondition();
    
        public static void main(String[] args) throws InterruptedException {
            Thread thread1 = new Thread(new ThreadDemo(one,two),"thread-1");
            Thread thread2 = new Thread(new ThreadDemo(two,three),"thread-2");
            Thread thread3 = new Thread(new ThreadDemo(three,one),"thread-3");
            thread1.start();
            // 稍微等待下,以免线程乱序执行
            Thread.sleep(100);
            thread2.start();
            Thread.sleep(100);
            thread3.start();
        }
    
       private static class ThreadDemo implements Runnable{
            // 当前线程锁通知条件
            private Condition condition;
            // 保存的下一个线程锁通知条件
            private Condition nextCondition;
    
            ThreadDemo(Condition condition,Condition nextCondition){
                this.condition = condition;
                this.nextCondition = nextCondition;
            }
    
            @Override
            public void run() {
                while (true){
                    lock.lock();
                    try {
                        System.out.println(Thread.currentThread().getName()+":"+count++);
                        try {
                            // 唤醒下一个线程
                            nextCondition.signal();
                            // 睡眠一下防止执行太快
                            Thread.sleep(500);
                            // 休眠当前线程
                            condition.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }finally {
                        lock.unlock();
                    }
                }
            }
        }
    }
    

    大致流程

    流程图

    方法二

    利用队列(Queue)volatileLockSupport::park,LockSupport:unpark实现。

    public class QueueTest{
    
        public static volatile int count = 1;
        public static final int MAX_COUNT = 100;
        public static final int MAX_THREAD_NUM = 3;
        public static volatile boolean flag = true;
        // 无界的队列,使用有界队列时需注意线程数要小于等于队列长度
        public static final Queue queue = new LinkedBlockingQueue();
    
        public static void main(String[] args){
            // 循环增加线程到阻塞队列
            for (int i = 1; i <= MAX_THREAD_NUM ; i++) {
                queue.add(new Thread(()->{
                    while (true){
                        // 将当前线程追加到队列尾部
                        queue.add(Thread.currentThread());
                        System.out.println(Thread.currentThread().getName() + ":" + count++);
                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        // 让主线程中的循环得以继续
                        flag  = true;
                        // 暂停当前线程
                        LockSupport.park(Thread.currentThread());
                    }
                },"Thread-"+i));
            }
    
           while (count < MAX_COUNT){
               // 利用volatile的可见性来保证线程执行的顺序性
               if (flag) {
                   flag = false;
                   Thread thread;
                   // 取出队列中的线程来执行
                   if ((thread = (Thread) queue.poll()) != null) {
                       Thread.State state = thread.getState();
                       //如果为未启动状态,则先启动
                       if (state == Thread.State.NEW) {
                           thread.start();
                       // 如果为等待状态则解除等待
                       } else if (state == Thread.State.WAITING) {
                           LockSupport.unpark(thread);
                       }
                   }
               }
           }
           // 中断线程,安全退出
           Thread thread;
           while ((thread = (Thread) queue.poll()) != null) {
               thread.interrupt();
           }
    
        }
    }
    

    大致流程

    图片.png

    能力有限,如有错误,欢迎指点。。。

    相关文章

      网友评论

          本文标题:JAVA并发如何让线程顺序执行

          本文链接:https://www.haomeiwen.com/subject/bbbcnhtx.html