现成程序中的Test类中的代码在不断地产生数据,然后交给TestDo.doSome()方法去处理,就好像生产者在不断地产生数据,消费者在不断消费数据。请将程序改造成有10个线程来消费生成者产生的数据,这些消费者都调用TestDo.doSome()方法去进行处理,故每个消费者都需要一秒才能处理完,程序应保证这些消费者线程依次有序地消费数据,只有上一个消费者消费完后,下一个消费者才能消费数据,下一个消费者是谁都可以,但要保证这些消费者线程拿到的数据是有顺序的。原始代码如下:
public class Test { public static void main(String[] args) { System.out.println("begin:"+(System.currentTimeMillis()/1000)); for(int i=0;i<10;i++){ //这行不能改动 String input = i+""; //这行不能改动 String output = TestDo.doSome(input); System.out.println(Thread.currentThread().getName()+ ":" + output); } } } //不能改动此TestDo类 class TestDo { public static String doSome(String input){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } String output = input + ":"+ (System.currentTimeMillis() / 1000); return output; } }
解题思路:使用信号灯和同步队列,信号灯可以控制有序的处理数据,在同步队列中一个读操作必须同步对应一个写操作。
public class Test { public static void main(String[] args) { /*创建一个信号灯(只有一个信号灯)*/ final Semaphore semaphore = new Semaphore(1); /*创建一个同步队列*/ final SynchronousQueue<String> queue = new SynchronousQueue<String>(); /*循环模拟十个线程*/ for(int i=0;i<10;i++){ new Thread(new Runnable(){ @Override public void run() { try { /*获取一个信号灯*/ semaphore.acquire(); /*从队列中取出一个数据*/ String input = queue.take(); /*把数据给doSome*/ String output = TestDo.doSome(input); /*打印*/ System.out.println(Thread.currentThread().getName()+ ":" + output); /*释放信号灯*/ semaphore.release(); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } System.out.println("begin:"+(System.currentTimeMillis()/1000)); for(int i=0;i<10;i++){ //这行不能改动 String input = i+""; //这行不能改动 try { /*往队列中添加数据*/ queue.put(input); } catch (InterruptedException e) { e.printStackTrace(); } } } } //不能改动此TestDo类 class TestDo { public static String doSome(String input){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } String output = input + ":"+ (System.currentTimeMillis() / 1000); return output; } }