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

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

通过wait/notify实现

package test.printThread.test2;

/** * * <p>Title: PrintABCUsingWaitNotify.java</p> * <p>Description: * ABCABCABCABCABCABCABCABCABCABC * <p> * @author tianqb * @mail tqb820965236@163.com * @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;

/** * * <p> * Title: PrintABCUsingWaitNotify.java * </p> * <p> * Description: * AAAAAAAAAABBBBBBBBBBCCCCCCCCCC * <p> * * @author tianqb * @mail tqb820965236@163.com * @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();
	}
}

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

全部评论

相关推荐

吐泡泡的咸鱼:我也工作了几年了,也陆陆续续面试过不少人,就简历来说,第一眼学历不太够,你只能靠你的实习或者论文或者项目经历,然后你没有论文,没有含金量高的比赛和奖项,只能看实习和项目,实习来说,你写的实习经历完全不清楚你想找什么工作?行研?数据分析?且写的太少了,再看项目,这些项目先不说上过大学读过研究生的都知道很水,然后对你想找的岗位有什么帮助呢?项目和实习也完全不匹配啊,你好像在努力将你所有的经历都放在简历里想表现你的优秀,但是对于你想找的岗位来说,有什么用呢?最后只能获得岗位不匹配的评价。所以你需要明白你想要找的岗位要求是什么,是做什么的,比如产品经理,然后再看你的经历里有什么匹配的上这个岗位,或者对这个岗位以及这个岗位所在的公司有价值,再写到你的简历上
点赞 评论 收藏
分享
05-11 11:48
河南大学 Java
程序员牛肉:我是26届的双非。目前有两段实习经历,大三上去的美团,现在来字节了,做的是国际电商的营销业务。希望我的经历对你有用。 1.好好做你的CSDN,最好是直接转微信公众号。因为这本质上是一个很好的展示自己技术热情的证据。我当时也是烂大街项目(网盘+鱼皮的一个项目)+零实习去面试美团,但是当时我的CSDN阅读量超百万,微信公众号阅读量40万。面试的时候面试官就告诉我说觉得我对技术挺有激情的。可以看看我主页的美团面试面经。 因此花点时间好好做这个知识分享,最好是单拉出来搞一个板块。各大公司都极其看中知识落地的能力。 可以看看我的简历对于博客的描述。这个帖子里面有:https://www.nowcoder.com/discuss/745348200596324352?sourceSSR=users 2.实习经历有一些东西删除了,目前看来你的产出其实很少。有些内容其实很扯淡,最好不要保留。有一些点你可能觉得很牛逼,但是面试官眼里是减分的。 你还能负责数据库表的设计?这个公司得垃圾成啥样子,才能让一个实习生介入数据库表的设计,不要写这种东西。 一个公司的财务审批系统应该是很稳定的吧?为什么你去了才有RBAC权限设计?那这个公司之前是怎么处理权限分离的?这些东西看着都有点扯淡了。 还有就是使用Redis实现轻量级的消息队列?那为什么这一块不使用专业的MQ呢?为什么要使用redis,这些一定要清楚, 就目前看来,其实你的这个实习技术还不错。不要太焦虑。就是有一些内容有点虚了。可以考虑从PR中再投一点产出
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务