实现三个线程轮流执行顺序打印ABC

这道题目在多线程的面试题中可能遇到的比较多,由于最近一直在学习Java多线程编程的知识,这里做一个总结,总结的可能并不是很全面,有问题或者有更好的编程方法也欢迎大家指出。
这道题目的实现方式很多,这里就以我了解的进行一个总结。
首先,我们看一下题目:
有三个线程A、B、C,采用多线程的方式使三个线程轮流执行顺序打印ABC 10次,结果如下:
在这里插入图片描述

通过wait/notify实现

package test.printThread.test2;

/**
 * 
 * 

Title: PrintABCUsingWaitNotify.java

*

Description: * ABCABCABCABCABCABCABCABCABCABC *

* @author tianqb * @mail [email protected] * @date 2019年6月7日下午5:29:39 * @version 1.0 * */ public class PrintABCUsingWaitNotify { private int times;// 打印的次数 private int state = 0;// 打印的状态 private Object objectA = new Object(); private Object objectB = new Object(); private Object objectC = new Object(); public PrintABCUsingWaitNotify(int times) { super(); this.times = times; } public void printA(){ print("A", 0, objectA, objectB); } public void printB(){ print("B", 1, objectB, objectC); } public void printC(){ print("C", 2, objectC, objectA); } public void print(String name, int targetState, Object curr, Object next){ for (int i = 0; i < times;) { synchronized (curr) { while(state % 3 != targetState){ try { curr.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } i++; state++; System.out.print(name); synchronized (next) { next.notify(); } } } } public static void main(String[] args) { PrintABCUsingWaitNotify p = new PrintABCUsingWaitNotify(10); new Thread(new Runnable() { @Override public void run() { p.printA(); } }).start(); new Thread(new Runnable() { @Override public void run() { p.printB(); } }).start(); new Thread(new Runnable() { @Override public void run() { p.printC(); } }).start(); } }

这里对题目进行一个扩展,顺序执行打印AAAAAAAAAABBBBBBBBBBCCCCCCCCCC

package test.printThread.test3;

/**
 * 
 * 

* Title: PrintABCUsingWaitNotify.java *

*

* Description: * AAAAAAAAAABBBBBBBBBBCCCCCCCCCC *

* * @author tianqb * @mail [email protected] * @date 2019年6月7日下午5:29:58 * @version 1.0 * */ public class PrintABCUsingWaitNotify { private int times;// 打印的次数 private int state = 0;// 打印的状态 private Object objectA = new Object(); private Object objectB = new Object(); private Object objectC = new Object(); public PrintABCUsingWaitNotify(int times) { super(); this.times = times; } public void printA() { print("A", 0, objectA, objectB); } public void printB() { print("B", 1, objectB, objectC); } public void printC() { print("C", 2, objectC, objectA); } public void print(String name, int targetState, Object curr, Object next) { synchronized (curr) { while (state % 3 != targetState) { try { curr.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } state++; for (int i = 0; i < times; i++) { System.out.print(name); } synchronized (next) { next.notify(); } } } public static void main(String[] args) { PrintABCUsingWaitNotify p = new PrintABCUsingWaitNotify(10); new Thread(new Runnable() { @Override public void run() { p.printC(); } }).start(); new Thread(new Runnable() { @Override public void run() { p.printB(); } }).start(); new Thread(new Runnable() { @Override public void run() { p.printA(); } }).start(); } }

通过join()方法实现(这种方法若题目要求只打印ABC一次,可以采用,若多次打印ABC,调用的就不是start()方法了,而是run()方法,因为start()方法在调用一次之后线程状态发生改变,再次调用会抛出IllegalThreadStateException,源码如下)

public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
}

实现代码:

package test.printThread.test4;

public class PrintABCUsingJoin {
	public static void main(String[] args) {
		Thread a  = new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.print("A");
			}
		});
		Thread b  = new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					a.join();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.print("B");
			}
		});
		Thread c  = new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					b.join();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.print("C");
			}
		});
		
		for (int i = 0; i < 10; i++) {
				a.run();
				b.run();
				c.run();
		}
	}
}

通过isAlive方法实现(限制如join方法)

package test.printThread.test5;

public class PrintABCUsingIsAlive {
	public static void main(String[] args) throws InterruptedException {
		Thread A = new Thread(() -> {
			System.out.print("A");
		});
		Thread B = new Thread(() -> {
			System.out.print("B");
		});
		Thread C = new Thread(() -> {
			System.out.print("C");
		});

		int i = 10;
		while (i > 0) {
			A.run();
			while (A.isAlive()) {
			}
			B.run();
			while (B.isAlive()) {
			}
			C.run();
			while (C.isAlive()) {
			}

			i--;
		}
	}
}

使用Lock和Condition对象实现(等待/唤醒)

package chapter4.locks.printABC;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class PrintABC {
	private int times;
	private int count = 0;
	
	private Lock lock = new ReentrantLock();
	private Condition c1 = lock.newCondition();
	private Condition c2 = lock.newCondition();
	private Condition c3 = lock.newCondition();
	
	public PrintABC(int times) {
		super();
		this.times = times;
	}
	
	public void print(int target, Condition curr, Condition next){
		for (int i = 0; i < times;) {
			try {
				lock.lock();
				while(count % 3 != target){
					curr.await();
				}
				System.out.print(Thread.currentThread().getName());
				count++;
				i++;
				next.signalAll();
			} catch (InterruptedException e) {
				e.printStackTrace();
			} finally {
				lock.unlock();
			}
		}
	}
	
	public void printA(){
		print(0, c1, c2);
	};
	
	public void printB(){
		print(1, c2, c3);
	};
	
	public void printC(){
		print(2, c3, c1);
	};
	
}
package chapter4.locks.printABC;

public class Run {
	public static void main(String[] args) {
		PrintABC p = new PrintABC(10);
		
		new Thread(() -> {
			p.printA();
		},"A").start();
		
		new Thread(() -> {
			p.printB();
		},"B").start();
		
		new Thread(() -> {
			p.printC();
		},"C").start();
	}
}

目前了解的就这么些了,之后学习到新的方法继续更新。

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