zoukankan      html  css  js  c++  java
  • 多线程通信笔试题

    一道关于多线程通信的笔试题,个人觉得值得推荐。
    问题描述:

    子线程循环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();
            }
        }
    }
  • 相关阅读:
    BZOJ3560: DZY Loves Math V(欧拉函数)
    BZOJ2693: jzptab(莫比乌斯反演)
    洛谷P1829 [国家集训队]Crash的数字表格 / JZPTAB(莫比乌斯反演)
    BZOJ3884: 上帝与集合的正确用法(欧拉函数 扩展欧拉定理)
    codeforces757E. Bash Plays with Functions(狄利克雷卷积 积性函数)
    等差数列与等比数列
    Codeforces#498F. Xor-Paths(折半搜索)
    在驱动和应用程序间共享内存
    Documentation/sched-bwc.txt 的中文翻译
    Windows NT 驱动程序开发人员提示 -- 应注意避免的事项
  • 原文地址:https://www.cnblogs.com/DarrenChan/p/5743219.html
Copyright © 2011-2022 走看看