阿里的在线评测题:多线程打印数据

我答的不好,那个伯乐在线评测系统不会用,本地写代码跑不成功挂了,总结下供后人参考。

  题目:

顺序递增打印正整数,从1开始打印到100,中间换行分隔。不允许重复打印出相同的数字,比如打印结果里出现2个5,3个6之类的。
要求如下:
1、使用三个线程A、B、C,其中线程A打印3的倍数,B打印5的倍数,C打印其他数字。

这个题目还是比较考察多线程功力的,因为常规的加锁、或者使用join、countdownlantch等我熟悉的已经失效了。我尝试了使用condition的wait,notify来3个线程互相唤醒。还是出现了加锁异常的情况:java.lang.IllegalMonitorStateException。从难度上来看,也比常见的两个线程交替打印奇、偶数要复杂。

       咨询了13哥。他的公众号:互联网架构师养成计划,可以看看。主要整理的干货不怎么挂上来,私聊就有。

13哥给出方案是使用信号量:Semaphore。我之前没有用过,给我的印象就是类似限流使用的,

常见的方法就是:

 semaphore.acquire();获取许可,

semaphore.release();释放许可。

抢不到的情况下会被hold.效率很高。有更好的结果也可以反馈下。

贴一下代码:

/**
 * 
 * @author 13哥
 *
 */
public class ShowSemaphore {
	
	//计数器
    final static AtomicInteger count = new AtomicInteger(0);
    //信号量
    static Semaphore sp3 = new Semaphore(1);
    static Semaphore sp5 = new Semaphore(1);
    static Semaphore other = new Semaphore(1);
    
    public static void main(String[] args) {

        
    	Thread threadA  =new Thread(new Runnable() {
	        @Override
	        public void run() {
            while(true) {
                int p =  count.get();
                if(p>100){
                    break;
                }
                if((p % 3 == 0) && (p % 5 != 0)) {
                    sp3.acquireUninterruptibly();
                    System.out.println("threadA :" + p);
                    count.getAndIncrement();
                }
                sp5.release();
                other.release();
            }
        }
  	  });

  	Thread threadB   =new Thread(new Runnable() {
  		@Override
        public void run() {
            while(true) {
                int p =  count.get();
                if(p>100){
                    break;
                }
                if((p % 5 == 0) && (p % 3 != 0)) {
                    sp5.acquireUninterruptibly();
                    System.out.println("threadB : " + p);
                    count.getAndIncrement();
                }
                sp3.release();
                other.release();
            }
        }
  	});

  	Thread threadC   =new Thread(new Runnable() {
      		@Override
            public void run() {
            while(true) {
                int p = count.get();
                if(p>100){
                    break;
                }
                if(((p % 5 != 0) && (p % 3 != 0)||(p % 15 == 0))) {
                    other.acquireUninterruptibly();
                    System.out.println("threadc : " + p);
                    count.getAndIncrement();
                }
                sp3.release();
                sp5.release();
            }
        }
        });	

  	threadA.start();
  	threadB.start();
	threadC.start();
  		
  		
    }
    
}

输出结果:

threadc : 0
threadc : 1
threadc : 2
threadA :3
threadc : 4
threadB : 5
threadA :6
threadc : 7
threadc : 8
threadA :9
threadB : 10
threadc : 11
threadA :12
threadc : 13
threadc : 14
threadc : 15
threadc : 16
threadc : 17
threadA :18
threadc : 19
threadB : 20
threadA :21
threadc : 22
threadc : 23
threadA :24
threadB : 25
threadc : 26
threadA :27
threadc : 28
threadc : 29
threadc : 30
threadc : 31
threadc : 32
threadA :33
threadc : 34
threadB : 35
threadA :36
threadc : 37
threadc : 38
threadA :39
threadB : 40
threadc : 41
threadA :42
threadc : 43
threadc : 44
threadc : 45
threadc : 46
threadc : 47
threadA :48
threadc : 49
threadB : 50
threadA :51
threadc : 52
threadc : 53
threadA :54
threadB : 55
threadc : 56
threadA :57
threadc : 58
threadc : 59
threadc : 60
threadc : 61
threadc : 62
threadA :63
threadc : 64
threadB : 65
threadA :66
threadc : 67
threadc : 68
threadA :69
threadB : 70
threadc : 71
threadA :72
threadc : 73
threadc : 74
threadc : 75
threadc : 76
threadc : 77
threadA :78
threadc : 79
threadB : 80
threadA :81
threadc : 82
threadc : 83
threadA :84
threadB : 85
threadc : 86
threadA :87
threadc : 88
threadc : 89
threadc : 90
threadc : 91
threadc : 92
threadA :93
threadc : 94
threadB : 95
threadA :96
threadc : 97
threadc : 98
threadA :99
threadB : 100

还有个是常规日志输出的题目,不贴了。

常规的读文件,一行行的处理,截取URL,统计应该还OK。

要是日志很大,而且URL复杂(需要考虑放到内存处理比如map会爆掉的情况)

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值