1:
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
/*
* 第一题:
* 现有的程序代码模拟产生了16个日志对象,
* 并且需要运行16秒才能打印完这些日志,
* 请在程序中增加4个线程去调用parseLog()方法来分头打印这16个日志对象,
* 程序只需要运行4秒即可打印完这些日志对象。
*/
public class Test1 {
public static void main(String[] args){
final BlockingQueue<String> queue = new ArrayBlockingQueue<String>(4);
System.out.println("begin:"+(System.currentTimeMillis()/1000));
/*模拟处理16行日志,下面的代码产生了16个日志对象,当前代码需要运行16秒才能打印完这些日志。
修改程序代码,开四个线程让这16个对象在4秒钟打完。
*/
for (int j = 0; j < 4; j++) {
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
for(int i=0;i<4;i++){
Test1.parseLog(Thread.currentThread().getName()
+"----"+ queue.take());
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}}).start();
}
for(int i=0;i<16;i++){ //这行代码不能改动
final String log = ""+(i+1);//这行代码不能改动
try {
queue.put(log);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//parseLog方法内部的代码不能改动
public static void parseLog(String log){
System.out.println(log+":"+(System.currentTimeMillis()/1000));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
2:
import java.util.Map;
import java.util.Stack;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Semaphore;
import java.util.concurrent.SynchronousQueue;
/*
* 第二题:
* 现成程序中的Test类中的代码在不断地产生数据,
* 然后交给TestDo.doSome()方法去处理,就好像生产者在不断地产生数据,
* 消费者在不断消费数据。请将程序改造成有10个线程来消费生成者产生的数据,
* 这些消费者都调用TestDo.doSome()方法去进行处理,故每个消费者都需要一秒才能处理完,
* 程序应保证这些消费者线程依次有序地消费数据,只有上一个消费者消费完后,
* 下一个消费者才能消费数据,下一个消费者是谁都可以,
* 但要保证这些消费者线程拿到的数据是有顺序的。
*/
public class Test2 {
public static void main(String[] args) {
//final BlockingQueue b = new ArrayBlockingQueue(1);
final Semaphore semaphore = new Semaphore(1);
//SynchronousQueue 一个put()后等待 一个take();反之亦然
final SynchronousQueue<String> queue = new SynchronousQueue<String>();
System.out.println("begin:" + (System.currentTimeMillis() / 1000));
for (int i = 0; i < 10; i++) {
new Thread(){
public void run() {
try {
/*时就只能有一个线程拿到许可了,而用只有1个空间的BlockQuee,
* 也可以阻塞其他线程
*/
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + "----"
+ TestDo.doSome(queue.take()));
semaphore.release();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.start();
}
for (int i = 0; i < 10; i++) { // 这行不能改动
String input = i + ""; // 这行不能改动
try {
queue.put(input);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
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;
}
}
3:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;
/*
* 第三题:成员key相同,则线程要互斥
*/
//不能改动此Test类
public class Test3 extends Thread {
private TestDoFor testDo;
private String key;
private String value;
public Test3(String key, String key2, String value) {
this.testDo = TestDoFor.getInstance();
/*
* 常量"1"和"1"是同一个对象,下面这行代码就是要用"1"+""的方式产生新的对象,
* 以实现内容没有改变,仍然相等(都还为"1"),但对象却不再是同一个的效果
*/
this.key = key + key2;
this.value = value;
}
public static void main(String[] args) throws InterruptedException {
final Test3 a = new Test3("1", "", "1");
final Test3 b = new Test3("1", "", "2");
final Test3 c = new Test3("3", "", "3");
final Test3 d = new Test3("4", "", "4");
System.out.println("begin:" + (System.currentTimeMillis() / 1000));
a.start();
b.start();
c.start();
d.start();
}
@Override
public void run() {
{
testDo.doSome(key, value);
}
}
@Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
Test3 t = (Test3) obj;
if (key.equals(t.key)) {
return true;
}
return false;
}
@Override
public int hashCode() {
// TODO Auto-generated method stub
return 1;
}
}
class TestDoFor {
private TestDoFor() {
}
private static TestDoFor _instance = new TestDoFor();
public static TestDoFor getInstance() {
return _instance;
}
private CopyOnWriteArrayList keys = new CopyOnWriteArrayList();
//private ArrayList keys = new ArrayList();
public void doSome(Object key, String value) {
Object o = key;
if (!keys.contains(o)) {
keys.add(o);
} else {
//用这个方法运行结果也可以,
/* for (int i = 0; i<keys.size();i++) {
System.out.println(keys.size());
Object oo = keys.get(i);
if(oo.equals(o)) {
o = oo;
}
}*/
/*
* 用Arraylist,迭代器在next()时,如刚好有线程 先做:keys.add(),
* 那么就会发生java.util.ConcurrentModificationException
*
* 用同步集合: CopyOnWriteArrayList,就不会发生这种异常了
*/
for (Iterator it = keys.iterator(); it.hasNext();) {
Object oo = it.next();
try {
Thread.sleep(20);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(oo.equals(o)) {
o = oo;
}
}
} synchronized(o)
// 以大括号内的是需要局部同步的代码,不能改动!
{
try {
Thread.sleep(1000);
System.out.println(key+":"+value + ":"
+ (System.currentTimeMillis() / 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
并发 Collection:
ConcurrentHashMap、CopyOnWriteArrayList 和 CopyOnWriteArraySet、CopyOnWriteArrayList :分别是HashMap、Arraylist、Set 对应的同步并发集合ConcurrentSkipListMap:有顺序的Map同步集合,可以用比较器Comparator参与构造
ConcurrentSkipListSet:有顺序的Set同步集合,可以用比较器Comparator参与构造