多线程练习(三)三个线程交互打印

曾经有面试官问过这样一个问题,如何让两个线程交替打印奇数和偶数?如何让多个线程交替执行?

回答这个问题之前需要先了解java多线程的运行机制,线程间通信机制,线程同步问题。

这个问题我知道的实现方案有两种,一种是基于synchronized和wait/notify,另外一种是基于Lock和Condition.

1.基于synchronized和wait/notify

public class ChangeABC {
    private Object lock = new Object();
    private boolean RUN0 = true;
    private static final int LIMIT = 10;

    public static void main(String[] args) throws InterruptedException {
        final ChangeABC o = new ChangeABC();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    o.m0();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "t0").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    o.m1();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "t1").start();
        Thread.sleep(10 * 1000);
    }

    private void m1() throws InterruptedException {
        for (int i = 1; i < LIMIT; i += 2) {
            synchronized (lock) {
                if (RUN0) {
                    lock.wait();
                }
                System.out.println(Thread.currentThread().getName() + "___" + i);
                RUN0 = true;
                lock.notify();
            }
        }
    }

    private void m0() throws InterruptedException {
        for (int i = 0; i < LIMIT; i += 2) {
            synchronized (lock) {
                if (!RUN0) {
                    lock.wait();
                }
                System.out.println(Thread.currentThread().getName() + "___" + i);
                RUN0 = false;
                lock.notify();
            }
        }
    }
}


2.基于Lock和Condition


import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/*** 线程间通信-基于lock的condition* @date 2017年12月21日*/
public class ChangeABC1 {
    private Lock lock = new ReentrantLock();
    private Condition c0 = lock.newCondition();
    private Condition c1 = lock.newCondition();
    private Condition c2 = lock.newCondition();
    private int status = 0;
    private static final int LIMIT = 10;

    public static void main(String[] args) throws InterruptedException {
        ExecutorService exec = new ThreadPoolExecutor(3, 30, 60, TimeUnit.SECONDS, new LinkedBlockingQueue(300), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        final ChangeABC1 o = new ChangeABC1();
        exec.submit(o.createTask(0));
        exec.submit(o.createTask(1));
        exec.submit(o.createTask(2));
        exec.shutdown();
        exec.awaitTermination(5, TimeUnit.MINUTES);
    }

    /*** @param name* @param i*/
    private Runnable createTask(final int i) {
        return new Runnable() {
            @Override
            public void run() {
                try {
                    m(i);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
    }

    private void m(final int n) throws InterruptedException {
        for (int i = n; i < LIMIT; i += 3) {
            lock.lock();
            try {
                switch (n) {
                    case 0:
                        if (status != 0) {
                            c0.await();
                        }
                        System.out.println(Thread.currentThread().getName() + "___" + i);
                        status = 1;
                        c1.signal();
                        break;
                    case 1:
                        if (status != 1) {
                            c1.await();
                        }
                        System.out.println(Thread.currentThread().getName() + "___" + i);
                        status = 2;
                        c2.signal();
                        break;
                    case 2:
                        if (status != 2) {
                            c2.await();
                        }
                        System.out.println(Thread.currentThread().getName() + "___" + i);
                        status = 0;
                        c0.signal();
                        break;
                    default:
                        break;
                }
            } finally {
                lock.unlock();
            }
        }
    }
}



链接:https://www.jianshu.com/p/dcc66a6f37cb

你可能感兴趣的:(线程)