美文网首页
如何使用ReentrantLock实现线程顺序执行

如何使用ReentrantLock实现线程顺序执行

作者: edolovee | 来源:发表于2018-03-09 20:24 被阅读0次

简介

最近遇到一个面试题目,如何实现使用多个线程以固定顺序打印字母,例如线程A打印字母“A”,线程B打印线程字母“B”,线程C打印字母“C”,要求控制台打印的内容是ABCABC。。。

好久没有使用这个ReentrantLock对于它的方法的使用有些模糊了,这里回忆下顺便也能加深下记忆。

ReentrantLock方法介绍

  1. lock 获得锁资源,如果被其他线程获取,则阻塞等待
  2. lockInterruptibly 与lock的不同之处在于它等待锁资源时响应中断,抛出中断状态
  3. tryLock 立即获取锁,即使获取不到不阻塞
  4. newCondition 生成一个该锁资源的条件,可以支持完成Object 监控器(wait notify notifyAll)

Condition方法介绍

  1. await 等待被signalled或者被中断
  2. signal 唤醒一个等待的线程重新获取锁
  3. signalAll 唤醒所有等待的线程重新获取锁

实现

理解了这些方法那么实现就简单了,代码如下

package com.ee;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockTest {

    private static ReentrantLock lock = new ReentrantLock();
    private static Condition a = lock.newCondition();
    private static Condition b = lock.newCondition();
    private static Condition c = lock.newCondition();
    private static AtomicInteger t = new AtomicInteger(0);
    private static final int THREADS = 3;
    
    public static void main(String[] args) {
        
        ReentrantLockTest lockTest = new ReentrantLockTest();
        
        ExecutorService pool = Executors.newFixedThreadPool(THREADS);
        pool.execute(lockTest.new PrintTask(a, b, "A", 0));
        pool.execute(lockTest.new PrintTask(b, c, "B", 1));
        pool.execute(lockTest.new PrintTask(c, a, "C", 2));
        
    }
    
    class PrintTask implements Runnable {
        //本线程的条件
        private Condition me;
        //下个线程的条件
        private Condition next;
        private String message;
        private int index;
        
        public PrintTask(Condition me, Condition next, String message, int index) {
            this.me = me;
            this.next = next;
            this.message = message;
            this.index = index;
        }
        
        @Override
        public void run() {
            while(true) {
                try {
                    lock.lock();
                    while(t.get() % THREADS != index) {
                        try {
                            //不到本线程的时机,则等待
                            me.await();
                        } catch (InterruptedException e) {
                            if (Thread.interrupted()) {
                                e.printStackTrace();
                            }
                        }
                    }
                    System.out.print(message);
                    t.incrementAndGet();
                    //通知其他线程重新获取锁,该他们执行了
                    next.signalAll();
                }finally {
                    lock.unlock();
                }
            }
        }
        
    }
}


相关文章

网友评论

      本文标题:如何使用ReentrantLock实现线程顺序执行

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