# 线程按照顺序执行实现方式

线程按照顺序执行实现方式

线程的状态

  • 初始(NEW):新建一个新的线程,还未调用start()。

  • 运行(RUNNABLE):已经准备就绪和正在运行中的两种状态都称为运行态,准备就绪的线程会放在线程池中等待被调用。

  • 阻塞(BLOCKED):某种原因放弃Cpu的使用权,等到线程进入就绪状态才有可能转换为运行态。

  • 等待(WAITING):该状态的线程需要等待其他线程中断或者做出通知。

  • 超时等待(TIME_WAITING):可以在制定的时间内自行返回。

  • 终止(TERMINATED):线程任务执行完毕。

Join实现线程顺序执行

将几个并行的线程合并为一个单线程执行,当一个线程必须等待另一个线程执行完毕后才能执行时,使用Join

public final void join();
public final synchronized void join(long millis);
public final synchronized void join(long millis, int nanos);
  • demo
public class ThreadJoinUse {
    
    

    private static final Logger logger = LoggerFactory.getLogger(ThreadJoinUse.class);


    class One extends Thread{
    
    
        @Override
        public void run() {
    
    
            logger.info("=====》我是One线程");
        }
    }

    class Two extends Thread{
    
    
        @Override
        public void run() {
    
    
            logger.info("=====》我是Two线程");
        }
    }

    class Three extends Thread{
    
    
        @Override
        public void run() {
    
    
            logger.info("=====》我是Three线程");
        }
    }

    @Test
    public void test1() throws InterruptedException {
    
    
        Thread thread1 = new Thread(new One());
        thread1.start();
        thread1.join();

        Thread thread2 = new Thread(new Two());
        thread2.start();
        thread2.join();

        Thread thread3 = new Thread(new Three());
        thread3.start();
        thread3.join();
    }
}

创建单一线程池实现顺序执行

创建一个只有一个线程的线程池操作,会创建一个线程队列,按FIFO的顺序执行里面的线程。

  • demo
@Test
public void test1(){
    
    
    ExecutorService executorService = Executors.newSingleThreadExecutor();
    Thread one = new One();
    Thread two = new Two();
    Thread three = new Three();
    executorService.submit(one);
    executorService.submit(two);
    executorService.submit(three);
    executorService.shutdown();
}

CountDownLatch(计数器) 实现线程顺序执行

使用juc包下的CountDownLatch实现按序执行线程。

  • demo
public class CountDawnLanchUse {
    
    

    private static final Logger logger = LoggerFactory.getLogger(ThreadJoinUse.class);
    
    class One extends Thread{
    
    

        int num;
        CountDownLatch countDownLatch;

        public One(int i, CountDownLatch countDownLatch) {
    
    
            this.num=i;
            this.countDownLatch=countDownLatch;
        }

        @Override
        public void run() {
    
    
            logger.info("=====》我是One线程");
            for (int i = 0; i < num; i++) {
    
    
                countDownLatch.countDown();
                logger.info("=====>线程one的数为:"+String.valueOf(countDownLatch.getCount()));
            }
        }
    }

    class Two extends Thread{
    
    

        int num;
        CountDownLatch countDownLatch;
        
        public Two(int i, CountDownLatch countDownLatch) {
    
    
            this.num=i;
            this.countDownLatch=countDownLatch;
        }

        @Override
        public void run() {
    
    
            logger.info("=====》我是Two线程");
            for (int i = 0; i < num; i++) {
    
    
                countDownLatch.countDown();
                logger.info("=====>线程two的数为:"+String.valueOf(countDownLatch.getCount()));

            }
        }
    }

    class Three extends Thread{
    
    
        
        int num;
        CountDownLatch countDownLatch;
        public Three(int i, CountDownLatch countDownLatch) {
    
    
            this.num=i;
            this.countDownLatch=countDownLatch;
        }

        @Override
        public void run() {
    
    
            logger.info("=====》我是Three线程");
            for (int i = 0; i < num; i++) {
    
    
                countDownLatch.countDown();
                logger.info("=====>线程three的数为:"+String.valueOf(countDownLatch.getCount()));
            }
        }
    }

    @Test
    public void test1(){
    
    
        int numOne = 10;
        int numTwo = 20;
        int numThree = 30;
        CountDownLatch oneCountDownLatch = new CountDownLatch(numOne);
        CountDownLatch twoCountDownLatch = new CountDownLatch(numTwo);
        CountDownLatch threeCountDownLatch = new CountDownLatch(numThree);
        Thread one = new One(numOne,oneCountDownLatch);
        one.start();
        try {
    
    
            oneCountDownLatch.await();
        } catch (InterruptedException interruptedException) {
    
    
            interruptedException.printStackTrace();
        }

        Thread two = new Two(numTwo,twoCountDownLatch);
        two.start();
        try {
    
    
            twoCountDownLatch.await();
        } catch (InterruptedException interruptedException) {
    
    
            interruptedException.printStackTrace();
        }

        Thread three = new Three(numThree,threeCountDownLatch);
        three.start();
        try {
    
    
            threeCountDownLatch.await();
        } catch (InterruptedException interruptedException) {
    
    
            interruptedException.printStackTrace();
        }

        logger.info("=====>主线程开始...");
    }
}

Object wait()使用

Object 的方法
  • wait():让正在对象上活动的线程进入等待状态,无限期等待,知道被唤醒为止。
  • notify():让正在当前对象上等待的线程唤醒。
  • notifyAll():唤醒当前对象上处于等待的所有线程。
synchronized()

wait()notify()建立在synchronized线程同步的基础上。

  • wait():释放当前对象占有的锁。
  • notify:通知不会释放锁。
wait()
  • 锁是锁对象,不是锁住线程。
  • Join是Thread对象的,wait是Object对象的,Join的底层实现使wait。
  • wait()使用必须在同步范围内不然会报如下的错。
Exception in thread "Thread-3" java.lang.IllegalMonitorStateException
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Object.java:502)
	at thread.ObjectWaitUse$Three.run(ObjectWaitUse.java:65)
  • wait()作用就是阻塞当前线程等待notify/notifyall()的唤醒,活等待超时后自动唤醒。

  • 底层就是ObjectMonitor对象释放了当前对象,丢掉waitSet区域去,然后重新锁住其他的对象。

完整例子,三个线程顺序执行
  • demo
public class ObjectWaitUse {
    
    

    private static final Logger logger = Logger.getLogger(ObjectWaitUse.class);

    private static Object objectOne = new Object();
    private static Object objectTwo = new Object();

    // 子线程是否运行完成的标志
    private static boolean oneRun = false;
    private static boolean twoRun = false;

    class One extends Thread {
    
    
        @Override
        public void run() {
    
    
            synchronized (objectOne) {
    
    
                logger.info("====================================》我是One线程");
                oneRun = true;
                objectOne.notify();
                logger.info("=====》One线程执行完成...");
            }
        }
    }

    class Two extends Thread {
    
    
        @Override
        public void run() {
    
    
            synchronized (objectOne) {
    
    
                try {
    
    
                    if (!oneRun) {
    
    
                        logger.info("=====>线程One没有执行完成,线程二等待中...");
                        objectOne.wait();
                    }
                    synchronized (objectTwo) {
    
    
                        logger.info("====================================》我是Two线程");
                        objectTwo.notify();
                        twoRun = true;
                        logger.info("=====》Two线程执行完成...");
                    }
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        }
    }

    class Three extends Thread {
    
    
        @Override
        public void run() {
    
    
            synchronized (objectTwo) {
    
    
                if (!twoRun) {
    
    
                    try {
    
    
                        logger.info("=====>线程Two没有执行完成,线程三等待中...");
                        objectTwo.wait();
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                }
                logger.info("====================================》我是Three线程");
                logger.info("======》Three线程执行完成...");
            }
        }
    }

    @Test
    public void test1() {
    
    
        Thread one = new One();
        one.start();
        Thread two = new Two();
        two.start();
        Thread three = new Three();
        three.start();
        try {
    
    
            Thread.sleep(5000);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        logger.info("=====>三个子线程结束...");
    }
}

使用ReentrantLock()实现

ReentrantLock()方法介绍
  • lock()获得锁资源,如果被其他线程获取,则阻塞等待。
  • lockInterruptibly 与lock的不同之处在于它等待锁资源时响应中断,抛出中断状态。
  • newCondition 生成一个该锁资源的条件,可以支持完成Object 监控器(wait notify notifyAll)。
newCondition方法介绍

Condition提供的await()signal()signalAll()原理和synchronized锁对象的wait()notify()notifyAll()是一致的,并且其行为也是一样的:

  • await()会释放当前锁,进入等待状态;
  • signal()会唤醒某个等待线程;
  • signalAll()会唤醒所有等待线程;
  • 唤醒线程从await()返回后需要重新获得锁。
使用例子
  • demo
public class ReentrantLockUse {
    
    

    private static final Logger logger = Logger.getLogger(ObjectWaitUse.class);

    /**
     * 创建可重入锁
     */
    private ReentrantLock reentrantLock = new ReentrantLock();

    private Condition oneCondition = reentrantLock.newCondition();
    private Condition twoCondition = reentrantLock.newCondition();
    private Condition threeCondition = reentrantLock.newCondition();

    private boolean oneFlag = false;
    private boolean twoFlag = false;

    class One extends Thread {
    
    
        @Override
        public void run() {
    
    
            // 创建锁
            reentrantLock.lock();
            try {
    
    
                logger.info("=====》One线程执行完成...");
                oneFlag = true;
                oneCondition.signalAll();
            } catch (Exception e) {
    
    
                e.printStackTrace();
            } finally {
    
    
                // 释放锁
                reentrantLock.unlock();
            }

        }
    }


    class Two extends Thread {
    
    
        @Override
        public void run() {
    
    
            reentrantLock.lock();
            try {
    
    
                while (!oneFlag){
    
    
                    logger.info("----->等待线程one执行完成");
                    twoCondition.await();
                }
                twoFlag = true;
                logger.info("=====》Two线程执行完成...");
                //通知其他线程重新获取锁,该他们执行了
                twoCondition.signalAll();
            } catch (Exception e) {
    
    
                e.printStackTrace();
            } finally {
    
    
                reentrantLock.unlock();
            }
        }
    }

    class Three extends Thread {
    
    
        @Override
        public void run() {
    
    
            reentrantLock.lock();
            try {
    
    
                while (!twoFlag){
    
    
                    logger.info("----->等待线程two执行完成");
                    twoCondition.await();
                }
                //通知其他线程重新获取锁,该他们执行了
                threeCondition.signalAll();
                logger.info("======》Three线程执行完成...");
            } catch (Exception e) {
    
    
                e.printStackTrace();
            } finally {
    
    
                reentrantLock.unlock();
            }
        }
    }

    @Test
    public void test1() throws InterruptedException {
    
    
        Thread one = new One();
        one.start();

        Thread two = new Two();
        two.start();

        Thread three = new Three();
        three.start();

        Thread.sleep(5000);
        logger.info("=====>三个子线程结束...");
    }

}

CyclicBarrier(回环栅栏)

通过它可以实现让一组线程等待至某个状态之后再全部同时执行。叫做回环是因为当所有等待线程都被释放以后,CyclicBarrier可以被重用。我们暂且把这个状态就叫做barrier,当调用await()方法之后,线程就处于barrier了。

private static final Logger logger = Logger.getLogger(CyclicBarrierUse.class);

private CyclicBarrier barrier1 = new CyclicBarrier(2);
private CyclicBarrier barrier2 = new CyclicBarrier(2);

class One extends Thread {
    
    
    @Override
    public void run() {
    
    
        try {
    
    
            logger.info("=====》One线程执行完成...");
            // 放开栅栏1
            barrier1.await();
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
    
    
            e.printStackTrace();
        }
    }
}


class Two extends Thread {
    
    
    @Override
    public void run() {
    
    
        try {
    
    
            // 放开栅栏1
            barrier1.await();
            logger.info("=====》Two线程执行完成...");
            // 放开栅栏2
            barrier2.await();
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
    
    
            e.printStackTrace();
        }
    }
}

class Three extends Thread {
    
    
    @Override
    public void run() {
    
    
        // 放开栅栏2
        try {
    
    
            barrier2.await();
            logger.info("======》Three线程执行完成...");
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
    
    
            e.printStackTrace();
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_37248504/article/details/110502016