现在的位置: 首页 > 综合 > 正文

多线程生产消费问题

2018年06月05日 ⁄ 综合 ⁄ 共 1739字 ⁄ 字号 评论关闭

现成程序中的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;
	}
}

抱歉!评论已关闭.