---------------------- 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控制线程数
应该像张老师那样用阻塞队列
详细请查看: http://edu.csdn.net/heima