黑马程序员---空中网面试题2

---------------------- android培训java培训、期待与您交流! ----------------------

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

这道题反复写了好几遍
题目的意思也有点含糊,理解了很久

换了许多种实现方式,感觉都搞不定
比如一开始想用一个10个线程的线程池
然后用ReentrantLock实现一次一个线程拿任务
感觉线程池没有起到作用,而且需要一个返回值
又要lock,混在一起没搞清楚

后来回去看了一眼java5线程并发库的那堆工具
发现了遗忘的Semaphore 就觉得这个很靠谱

而且之前想得有点多
取到值后的output不一定要获得
然后在原函数打印,在别的地方打印也是可以的

不过题目本身也比较绕
如果是类似生产线的话,10个线程应该是并发的
但是题目又要求1个线程处理数据时,其他线程不能进入

import java.util.concurrent.*;

public class QueueTest{

	static Semaphore sp=new Semaphore(1,true);			//用Semaphore控制始终只有一个线程进入

	public static void main(String[] args){

		System.out.println("begin:"+(System.currentTimeMillis()/1000));
		ExecutorService es=Executors.newFixedThreadPool(10);

		for(int i=0;i<10;i++){ // 这行不能改动
			String input=i+""; // 这行不能改动
			try{
				sp.acquire();
			}catch(InterruptedException e){
				e.printStackTrace();
			}
			es.execute(new Task2(sp,input));			//给线程池塞个任务
		}
	}
}

class Task2 implements Runnable{
	private String input;
	private Semaphore sp;

	public Task2(Semaphore sp,String input){
		this.sp=sp;
		this.input=input;
	}

	public void run(){
		String output=TestDo.doSome(input);
		System.out.println(Thread.currentThread().getName()+":"+output);
		sp.release();							//完事之后Semaphore重新开启
	}
}

// 不能改动此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;
	}
}

最后还是用的线程池
然后看张老师用的是阻塞队列
这个题应该用阻塞队列好
模型很切合

最后虽然实现了效果,但是感觉和题目要求有点出入
Test里面的用来产生数据的for循环感觉不应该放acquire
而是把数据放进队列
然后在出口那头用一个Semaphore控制线程数

应该像张老师那样用阻塞队列

---------------------- android培训java培训、期待与您交流! ----------------------
详细请查看: http://edu.csdn.net/heima
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值