空中网面试题

    1. 1. 空中网面试题1  
    2.   
    3. package com.kongzhongwang.interview;  
    4.   
    5. import java.util.concurrent.ArrayBlockingQueue;  
    6. import java.util.concurrent.BlockingQueue;  
    7.   
    8. //myeclipse强大功能:将代码直接复制到项目的src路径下可以自动相应生成包名和类名  
    9. /** 
    10.  *  
    11.  *    空中网面试题1:现有程序代码模拟产生16个日志对象,并且需要运行16秒才能打印完这些日志,请在程序中增加四个线程去调用 
    12.  * parseLog()方法来分头打印这16个日志对象,程序只需运行4秒即可打印完这些日志对象。 
    13.  * 考察新技术BlockingQueue 
    14.  */  
    15.   
    16. public class ReadLog {  
    17.     public static void main(String[] args) {  
    18.   
    19.         /*此处有一个巧合:这里ArrayBlockingQueue<String>(1)和ArrayBlockingQueue<String>(16) 
    20.          * 达到的效果一样,并且前者产生的数据组合更整齐;目前推测是巧合,希望大牛发现因果了告知一声 
    21.          */  
    22.         final BlockingQueue<String> queue = new ArrayBlockingQueue<String>(1);  
    23.         for (int i = 0; i < 4; i++) {  
    24.             new Thread(new Runnable() {  
    25.                 public void run() {  
    26.                     while (true) {  
    27.                         try {  
    28.                             String log = queue.take();  
    29.                             parseLog(log);  
    30.                         } catch (InterruptedException e) {  
    31.                             e.printStackTrace();  
    32.                         }  
    33.                     }  
    34.                 }  
    35.             }).start();  
    36.         }  
    37.         System.out.println("begin:" + (System.currentTimeMillis() / 1000));  
    38.         /* 
    39.          * 模拟处理16个日志,下面代码产生了16个日志对象;当前代码需要运行16秒才能打印完成这些日志对象; 
    40.          * 修改程序代码,开四个线程让16个对象在4秒内打完 
    41.          */  
    42.         for (int i = 0; i < 16; i++) { // 这行代码不能改动  
    43.             final String log = "" + (i + 1); // 这行代码不能改动  
    44.             {  
    45.                 // ReadLog.parseLog(log);  
    46.                 try {  
    47.                     queue.put(log);  
    48.                 } catch (InterruptedException e) {  
    49.                     e.printStackTrace();  
    50.                 }  
    51.             }  
    52.         }  
    53.     }  
    54.   
    55.     // parseLog内部代码不能动  
    56.     public static void parseLog(String log) {  
    57.         System.out.println(log + ":" + System.currentTimeMillis() / 1000);  
    58.         try {  
    59.             Thread.sleep(1000);  
    60.         } catch (InterruptedException e) {  
    61.             e.printStackTrace();  
    62.         }  
    63.     }  
    64. }  
    65. 2. 空中网面试题2  
    66.   
    67. package com.kongzhongwang.interview;  
    68.   
    69. import java.util.concurrent.Semaphore;  
    70. import java.util.concurrent.SynchronousQueue;  
    71.   
    72. /** 
    73.  *    空中网面试题2: 现成程序中的Test类中的代码在不断地产生数据,然后交给TestDo.doSome()方法去处理; 
    74.  * 这就好像是生产者在不断地产生数据,消费者在不断地消费数据。请将程序改造成有10个线程来消费生产者产生的数据, 
    75.  * 这些消费者都调用TestDo.doSome()方法去处理,固每个消费者都需要1秒才能处理完,程序应该保证这些 
    76.  * 消费者线程依次有序的消费数据,只有上一个消费者消费完后,下一个消费者才能消费数据,下一个消费者是谁都可以, 但要保证消费者拿到的数据是有顺序的。 
    77.  */  
    78. public class Test {  
    79.   
    80.     public static void main(String[] args) {  
    81.   
    82.         //使用semaphore信号灯相当于上一个lock锁  
    83.         final Semaphore semaphore = new Semaphore(1);  
    84.         //新的队列方式  
    85.         final SynchronousQueue<String> queue = new SynchronousQueue<String>();  
    86.         for(int i=0;i<10;i++){  
    87.             new Thread(new Runnable() {  
    88.                   
    89.                 @Override  
    90.                 public void run() {  
    91.                     try {  
    92.                         semaphore.acquire();  
    93.                         String input = queue.take();  
    94.                         String output = TestDo.doSome(input);  
    95.                         System.out.println(Thread.currentThread().getName() + ":" + output);  
    96.                         semaphore.release();  
    97.                     } catch (InterruptedException e) {  
    98.                         e.printStackTrace();  
    99.                     }  
    100.                 }  
    101.             }).start();  
    102.         }  
    103.         System.out.println("begin:" + (System.currentTimeMillis() / 1000));  
    104.   
    105.         for (int i = 0; i < 10; i++) { // 这行代码不能改动  
    106.             String input = i + ""// 这行代码不能改动  
    107.             try {  
    108.                 queue.put(input);  
    109.             } catch (InterruptedException e) {  
    110.                 e.printStackTrace();  
    111.             }  
    112.         }  
    113.     }  
    114. }  
    115.   
    116. // TestDo类不能动  
    117. class TestDo {  
    118.   
    119.     public static String doSome(String input) {  
    120.         try {  
    121.             Thread.sleep(1000);  
    122.         } catch (Exception e) {  
    123.             e.printStackTrace();  
    124.         }  
    125.         String output = input + ":" + (System.currentTimeMillis() / 1000);  
    126.         return output;  
    127.     }  
    128.   
    129. }  
    130.  3.空中网面试题3  
    131.   
    132. package com.kongzhongwang.interview;  
    133.   
    134. import java.util.ArrayList;  
    135. import java.util.Iterator;  
    136. import java.util.concurrent.CopyOnWriteArrayList;  
    137.   
    138. public class Tests extends Thread {  
    139.   
    140.     /** 
    141.      * 空中网面试题3: 现有程序同时启动了四个线程去调用TestDo.doSome(key,value)方法; 
    142.      * 由于TestsDo.doSome(key,value)方法内的代码是先暂停1秒,然后再输出以秒为单位的当前时间值, 
    143.      * 所以会打印出四个相同的时间值,如下所示:4:4 1258199615 1:1 1258199615 3:3 1258199615 2:2 
    144.      * 1258199615 ;请修改代码,如果有几个线程调用TestDo.doSome(key,value)方法时; 
    145.      * 传递进去的key值相等(equals比较为true),则这几个线程应互斥输出结果,即当有两个线程的key都为1时, 
    146.      * 它们中的一个要比其他线程晚一步输出结果,如下所示:4:4 1258199615 1:1 1258199615 3:3 1258199615 1:2 
    147.      * 1258199616 ;总之每个线程中指定的key相等时;这些相等的线程应每隔1秒输出时间值(要用互斥), 
    148.      * key不同,则并行执行(相互之间不互斥) 
    149.      */  
    150.   
    151.     private TestsDo testDo;  
    152.     private String key;  
    153.     private String value;  
    154.   
    155.     private Tests(String key, String key2, String value) {  
    156.         this.testDo = TestsDo.getInstance();  
    157.         /* 
    158.          * 常量“1”和“1”是同一个对象,下面这行代码就是要用“1”+“”的方式产生新的对象; 
    159.          * 以实现内容没有改变,仍然相等(都还为“1”),但对象却不再是同一个的效果 
    160.          */  
    161.         this.key = key + key2;  
    162.         /* 
    163.          * a = "1"+""; 
    164.          * b = "2"+""; 
    165.          * a和b是同一个对象,因为编译器在执行之前就会将其优化为 a=“1”; 
    166.          * 但是this.key = key + key2;这句,编译器不会给你优化, 
    167.          * 因为你是属性变量,编译器不知道你将来要传入什么值 
    168.          */  
    169.         this.value = value;  
    170.     }  
    171.   
    172.     public static void main(String[] args) {  
    173.   
    174.         Tests a = new Tests("1""""1");  
    175.         Tests b = new Tests("1""""2");  
    176.         Tests c = new Tests("3""""3");  
    177.         Tests d = new Tests("4""""4");  
    178.         System.out.println("begin:" + (System.currentTimeMillis() / 1000));  
    179.         a.start();  
    180.         b.start();  
    181.         c.start();  
    182.         d.start();  
    183.     }  
    184.   
    185.     public void run() {  
    186.         testDo.doSome(key, value);  
    187.     }  
    188. }  
    189.   
    190. class TestsDo {  
    191.     private TestsDo() {}  
    192.     private static TestsDo _instance = new TestsDo();  
    193.     public static TestsDo getInstance() {  
    194.         return _instance;  
    195.     }  
    196.     //传统写法,没有考虑到线程并发问题    
    197. //  private ArrayList keys = new ArrayList();  
    198.     private CopyOnWriteArrayList keys = new CopyOnWriteArrayList();  
    199.     public void doSome(Object key,String value){  
    200.         Object o = key;  
    201.         if(! keys.contains(o)){  
    202.             keys.add(o);  
    203.         }else{  
    204.             //迭代的过程中不能进行其他操作;  
    205.             for(Iterator iter = keys.iterator();iter.hasNext();){  
    206.                 /*这里的休眠作用:为了让大家看到,使用传统的private ArrayList keys = new ArrayList(); 
    207.                  * 会导致Exception in thread "Thread-1" java.util.ConcurrentModificationException异常 
    208.                  * 因为迭代的过程中不能进行其他操作;你非要在迭代的时候向其中添加数据就会导致这种异常,而且在迭代中放入休眠这种错误百发百中。 
    209.                  */  
    210.                 try {  
    211.                     Thread.sleep(20);  
    212.                 } catch (InterruptedException e) {  
    213.                     e.printStackTrace();  
    214.                 }  
    215.                 Object oo = iter.next();  
    216.                 if(o.equals(oo)){  
    217.                 o = oo;   
    218.                 }  
    219.             }  
    220.         }  
    221.         //这里为了区别是不同对象,所以不能直接使用synchronized(key)  
    222.         synchronized(o)  
    223.         //大括号内的是需要同步的代码,不能改动  
    224.         {  
    225.             try{  
    226.                 Thread.sleep(1000);  
    227.                 System.out.println(key+":"+value+":" + (System.currentTimeMillis() / 1000));  
    228.             }catch(Exception e){  
    229.                 e.printStackTrace();  
    230.             }  
    231.         }  
    232.     }  

转载于:https://www.cnblogs.com/chenchangyan/p/3539677.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值