多线程

多线程

线程状态

  • 初始
  • 就绪
  • 运行
  • 阻塞
  • 锁池
  • 结束

一些概念

CountDownLatch 与Semaphore区别

谈谈你对AQS的理解。AQS如何实现可重入锁?

  1. AQS(AbstractQueuedSynchronizer)是java线程同步的框架,是JDK中很多锁工具的核心实现框架。

  2. 在AQS中,维护了一个信号量state和一个线程组成的双向链表队列,其中,这个线程队列,就是用来给线程排队的,而state就像是一个红绿灯,用来控制线程排队或者放行的,在不同的场景下,有不同的意义

                +------+  prev +-----+       +-----+
           head |      | <---- |     | <---- |     |  tail
                +------+       +-----+       +-----+
    
    
  3. 在可重入锁这个场景下,state就用来表示加锁的次数。0标识为无锁,每加一次锁,state就加1,释放锁state就减1

有三个线程A、B、C,如何保证三个线程顺序执行、同时执行、交错执行

考点 :

  • CountDownLatch (减计数,await等待,countDown计数减1,为0时await线程唤醒,不循环)

  • CyclicBarrier(加计数,循环栅栏,线程组等待到齐,循环执行,await方法代表线程已经到达栅栏,计数加1)

  • Semaphore(信号量池,获取到信号才允许执行,release释放信号量,aquire申请信号量)

  1. 三个线程同时执行

    /**
     * @author tangmqb
     * @version 1.0.0
     * 2022/1/27
     * 三个线程同时进行
     */
    public class RunSameTimeDemo {
    
        public static void main(String[] args) throws InterruptedException {
            CountDownLatch countDownLatch = new CountDownLatch(1);
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        countDownLatch.await();
                        System.out.println("线程A run:" + System.currentTimeMillis());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        countDownLatch.await();
                        System.out.println("线程B run:" + System.currentTimeMillis());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        countDownLatch.await();
                        System.out.println("线程C run:" + System.currentTimeMillis());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
            Thread.sleep(500);
            countDownLatch.countDown();
        }
    }
    
  2. 顺序执行:信号量实现

    /**
     * @author tangmqb
     * @version 1.0.0
     * 2022/1/27
     * 顺序执行
     */
    public class RunByOrderDemo {
    
        public static void main(String[] args) {
            Semaphore semaphore = new Semaphore(1);
    
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        semaphore.acquire();
                        for (int i = 0; i < 10; i++) {
                            System.out.println("线程A"+i+",执行时间:"+System.currentTimeMillis());
                            Thread.sleep(500);
                        }
                        semaphore.release();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        semaphore.acquire();
                        for (int i = 0; i < 10; i++) {
                            System.out.println("线程B,执行时间:"+i+System.currentTimeMillis());
                            Thread.sleep(500);
                        }
                        semaphore.release();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        semaphore.acquire();
                        for (int i = 0; i < 10; i++) {
                            System.out.println("线程C,执行时间:"+i+System.currentTimeMillis());
                            Thread.sleep(500);
                        }
                        semaphore.release();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }
    
  3. 交替运行,循环栅栏实现

    /**
     * @author tangmqb
     * @version 1.0.0
     * 2022/1/27
     * 线程交替运行
     */
    public class RunByClicDemo {
        public static void main(String[] args) {
            //构造函数 参数1:多少个参与者,参数2:最后一个参与者到达时需要做的事
            CyclicBarrier cyclicBarrier = new CyclicBarrier(3, new Runnable() {
                @Override
                public void run() {
                    System.out.println("线程"+Thread.currentThread().getName() + "最后一个到达");
                }
            });
            for (int i = 0; i<3; i++) {
                new Thread1(String.valueOf(i),cyclicBarrier).start();
            }
    
        }
    }
    
    class Thread1 extends Thread {
        private CyclicBarrier barrier;
        public Thread1(String threadName,CyclicBarrier barrier){
            setName(threadName);
            this.barrier=barrier;
        }
        @Override
        public void run() {
            try {
                while (true) {
                    barrier.await();
                    System.out.println("线程"+getName()+"运行完成");
                    Thread.sleep(500);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
end