当线程处于就绪状态时,等待被分配到CPU时间片然后才真正开始执行,由于每个线程开始的时间不确定,因此也就不能唯一确定线程的执行顺序。如果想让线程有序执行,主要思路就是让子线程的执行在主线程中串行化,想到了以下几种让线程按顺序执行的方法

 

面试官:你说说如何让“线程”按序执行?_程序员

 

让线程按序执行的方法
JDK自带方法
join 等待线程执行终止的方法

可以在主线程中调用子线程的join()方法,让子线程按序执行,代码如下:

public static void main(String[] args) throws InterruptedException {

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("t1 do something");
            }
        });
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("t2 do something");
            }
        });
        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("t3 do something");
            }
        });

        t1.start();
        // 主线程阻塞等待子线程执行完
        t1.join();
        t2.start();
        // 主线程阻塞等待子线程执行完
        t2.join();
        t3.start();
        // 主线程阻塞等待子线程执行完
        t2.join();
        }

并发工具类
CountDownLatch

countDownLatch.await()会阻塞调用线程直到 state==0。因此,可以利用这个特性使得子线程按序执行


    private static CountDownLatch countDownLatch = new CountDownLatch(1);

    public static void main(String[] args) throws InterruptedException {

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("t1 do something");
                countDownLatch.countDown();
            }
        });
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("t2 do something");
                countDownLatch.countDown();
            }
        });
        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("t3 do something");
                countDownLatch.countDown();
            }
        });

        t1.start();
        // 主线程阻塞等待子线程执行完毕
        countDownLatch.await();
        t2.start();
        // 主线程阻塞等待子线程
        countDownLatch.await();
        t3.start();
        // 主线程阻塞等待子线程
        countDownLatch.await();
        }

CycleBarrier

如下有三个任务,分三个步骤执行,依次按照线程123执行 barrier.await()方法,可以让当前线程等待其他线程执行完毕

 static CyclicBarrier barrier = new CyclicBarrier(1, new Runnable() {
        @Override
        public void run() {
            System.out.println("barrier" + Thread.currentThread().getName());
        }
    });

    public static void main(String[] args) {

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("t1 do something");
                    barrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }

            }
        });
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("t2 do something");
                try {
                    barrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("t3 do something");
                try {
                    barrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }
        });

        t1.start();
        t2.start();
        t3.start();
    }

信号量

分别依次打印ABC,循环10次


public class ABCSemaphore {

    private static Semaphore A = new Semaphore(1);
    private static Semaphore B = new Semaphore(1);
    private static Semaphore C = new Semaphore(1);

    static class ThreadA extends Thread {

        @Override
        public void run() {
            try {
                for (int i = 0; i < 10; i++) {
                    A.acquire();
                    System.out.print("A");
                    B.release();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    static class ThreadB extends Thread {

        @Override
        public void run() {
            try {
                for (int i = 0; i < 4; i++) {
                    B.acquire();
                    System.out.print("B");
                    C.release();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    static class ThreadC extends Thread {

        @Override
        public void run() {
            try {
                for (int i = 0; i < 5; i++) {
                    C.acquire();
                    System.out.print("C");
                    A.release();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    public static void main(String[] args) throws InterruptedException {
        // 开始只有A可以获取, BC都不可以获取, 保证了A最先执行
        B.acquire();
        C.acquire();
        new ThreadA().start();
        new ThreadB().start();
        new ThreadC().start();
    }
}

放入线程池按照顺序执行

线程池中有很多线程去处理任务,不能够保证执行顺序,如果线程池可串行化,那么放入的任务可顺序执行,记得把线程池的线程数设置为1

    // 此处注意 线程数设置为1
 ExecutorService service = Executors.newFixedThreadPool(1);
        service.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("child thread1 do something ");
            }
        });
        service.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("child thread2 do something ");
            }
        });