多线程通信笔试题
一道关于多线程通信的笔试题,个人觉得值得推荐。
问题描述:
子线程循环10次,主线程循环100次,接着又回到子线程循环10次,接着又回到主线程循环100次。以此类推,总共循环50次。
问题分析:
显然,这是一道多线程的问题。由于开启多个线程之后,是靠CPU分发时间片运行的,谁拿到时间片谁运行。但是可能A线程刚好运行到一半,时间片就给了B线程,这样就会导致数据产生错误。由此,我们用synchronized进行上锁,即便拿到时间片,但由于上锁的对象(即钥匙)别的线程没有释放,所以也只能干等,直到时间片又被对方拿走,这样就避免了数据的错误。本题中,涉及到了两个线程循环执行,显然需要考虑线程间的通信,即wait()和notify()。这两个方法是object类的方法,如果在线程A中调用了obj.wait()方法,那么A就停止等待,等到其他线程调用obj.notify()方法为止。这时,obj显然成了多个线程之间的通信手段。
这里还要强调一点,wait()和notify()不可以轻易调用,他们必须包含在对应的synchronized语句中,他们都需要首先获得目标对象的一个监视器。
问题求解:
package thread; public class Demo5 { public static void main(String[] args) { final Business business = new Business(); new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 50; i++) { business.sub(i); } } }).start(); for (int i = 0; i < 50; i++) { business.main(i); } } static class Business { // 是否轮到子线程 boolean isSub = true; public synchronized void sub(int i) { // 如果没有轮到子线程,进去就阻塞 if (!isSub) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } for (int j = 0; j < 10; j++) { System.out.println("循环次数:" + (i + 1) + ",子线程" + (j + 1)); } isSub = false; this.notify(); } public synchronized void main(int i) { // 如果没有轮到主线程,进去就阻塞 if (isSub) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } for (int j = 0; j < 100; j++) { System.out.println("循环次数:" + (i + 1) + ",主线程" + (j + 1)); } isSub = true; this.notify(); } } }