关于多线程的面试题

题目:子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,接着又回到主线程又循环100次,如此循环50次。写出程序。

一、思路:

这是一道考察多线程的题目。应题目的要求,子线程循环10次和主线程循环100次的中途不能被打断,则须要在循环方法里面加入互斥锁。要连续有规律运行主线程和子线程,能够考虑当线程执行完一个周期的循环后,让线程休眠让出线程运行权,或者使用wita()和notify()方法。java

二、答案之一:

public class TranditionThreadCommunication {
	public static void main(String[] args) {

		final Business business = new Business();

		// 子线程循环
		new Thread(new Runnable() {
			@Override
			public void run() {
				for (int i = 1; i <= 50; i++) {
					try {
						business.sub(i);
					} catch (InterruptedException e) {
					}
				}
			}
		}).start();

		// 主线程循环
		for (int i = 1; i <= 50; i++) {
			try {
				business.mian(i);
			} catch (InterruptedException e) {
			}
		}

	}
}

/**
 * 业务类型(包含各色的同步锁)
 */
class Business {
	// sub()方法是否该运行标识
	private boolean bShouldSub = true;

	/**
	 * 循环100次打印的方法sub()
	 * 
	 * @param i
	 * @throws InterruptedException
	 */
	public synchronized void sub(int i) throws InterruptedException {
		while (!bShouldSub) { // 当 bShouldSub 为 false 时,则等待
			this.wait();
		}
		for (int j = 1; j <= 10; j++) {
			System.out.println("sub thread :   第" + i + "行, 第" + j + "列");
		}
		bShouldSub = false; // 执行for循环后,标志sub()方法不可再执行
		this.notify(); // 唤醒线程
	}

	/**
	 * 循环100次打印的方法mian()
	 * 
	 * @param i
	 * @throws InterruptedException
	 */
	public synchronized void mian(int i) throws InterruptedException {
		while (bShouldSub) {
			this.wait();
		}
		for (int j = 1; j <= 100; j++) {
			System.out.println("main thread :   第" + i + "行, 第" + j + "列");
		}
		bShouldSub = true; // 执行for循环后,标志sub()方法可再执行了
		this.notify(); // 唤醒线程
	}
}

三、经验:

(1)要用到共同数据(包括同步锁)或共同算法的若干个方法应该归在同一个类身上,这种设计体现了高类聚和程序的健壮性。像上面的循环10次和循环100次的操做都须要用到锁时,能够将这两个方法加上锁(synchronized)并放到Business类中。算法

(2)上面答案中的多线程

while (bShouldSub) {
			this.wait();
		}

借鉴了javaAPI 中的wait()方法的写法,主要是为了防止线程之间可能出现的伪唤醒。app

java API 中的wait()方法的原文以下:ide

public final void wait() throws InterruptedException 在其余线程调用此对象的 notify() 方法或 notifyAll() 方法前,致使当前线程等待。换句话说,此方法的行为就好像它仅执行 wait(0) 调用同样。 当前线程必须拥有此对象监视器。该线程发布对此监视器的全部权并等待,直到其余线程经过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。而后该线程将等到从新得到对监视器的全部权后才能继续执行。this

对于某一个参数的版本,实现中断和虚假唤醒是可能的,并且此方法应始终在循环中使用:线程

synchronized (obj) {
    while (<condition does not hold>)
        obj.wait();
     // Perform action appropriate to condition
}

此方法只应由做为此对象监视器的全部者的线程来调用。有关线程可以成为监视器全部者的方法的描述,请参阅 notify 方法。 抛出: IllegalMonitorStateException - 若是当前线程不是此对象监视器的全部者。 InterruptedException - 若是在当前线程等待通知以前或者正在等待通知时,任何线程中断了当前线程。在抛出此异常时,当前线程的中断状态 被清除。设计

相关文章
相关标签/搜索