您的位置:首页 > 编程语言 > Java开发

JAVA几个线程互斥排队输出结果

2014-12-07 10:22 141 查看
现有程序同时启动了4个线程去掉用TestDo.doSome(key,value)方法,由于TestDo.doSome(key,value)方法内的代码是先暂停1秒,然后再输出以秒为单位的当前时间值,所以,会打印4个相同的时间值,如下所示:

begin1417917472

3:3:1417917473

1:1:1417917473

4:4:1417917473

1:2:1417917473

请修改代码,如果有几个线程调用TestDo.doSome(key,value)方法时,传递进去的key相等(equals比较为true),则这几个线程应互斥排队输出结果,即当有两个线程的key都是”1”时,他们中的一个要比灵位其他线程晚一秒输出结果,如下所示:

begin1417917541

3:3:1417917542

1:1:1417917542

4:4:1417917542

1:2:1417917543

原来代码:
package cn.sync;

public class Test3 extends Thread{

private TestDo testDo;
private String key;
private String value;

public Test3(String key, String key2, String value) {
this.testDo  = TestDo.getInstance();
/*
常量"1"和"1"是同一个对象,下面这行代码是要用"1"+""的方式产生新对象
以实现内容没有改变,仍然相等(都还为"1"),但对象queue不再是同一个对象
*/
this.key = key + key2;
this.value = value;
}

public static void main(String[] args) {
// TODO Auto-generated method stub
Test3 a = new Test3("1","","1");
Test3 b = new Test3("1","","2");
Test3 c = new Test3("3","","3");
Test3 d = new Test3("4","","4");
System.out.println("begin" + (System.currentTimeMillis()/1000));
a.start();
b.start();
c.start();
d.start();
}

public void run() {
// TODO Auto-generated method stub
testDo.doSome(key, value);
}

}
class TestDo{
private TestDo(){}
private static TestDo _instance = new TestDo();
public static TestDo getInstance(){
return _instance;
}

public void doSome(Object key,String value){

//以大括号内的是需要局部同步的代码,不能改动
{
try {
Thread.sleep(1000);
System.out.println(key+":"+value+":"
+(System.currentTimeMillis()/1000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

答案代码:

package cn.sync;

import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;

public class AnswerTest3 extends Thread{

private TestDo testDo;
private String key;
private String value;

public AnswerTest3(String key, String key2, String value) {
this.testDo  = TestDo.getInstance();
/*
常量"1"和"1"是同一个对象,下面这行代码是要用"1"+""的方式产生新对象
以实现内容没有改变,仍然相等(都还为"1"),但对象queue不再是同一个对象
*/
this.key = key + key2;
this.value = value;
}

public static void main(String[] args) {
// TODO Auto-generated method stub
AnswerTest3 a = new AnswerTest3("1","","1");
AnswerTest3 b = new AnswerTest3("1","","2");
AnswerTest3 c = new AnswerTest3("3","","3");
AnswerTest3 d = new AnswerTest3("4","","4");
System.out.println("begin" + (System.currentTimeMillis()/1000));
a.start();
b.start();
c.start();
d.start();
}

public void run() {
// TODO Auto-generated method stub
testDo.doSome(key, value);
}

}
class TestDo{
private TestDo(){}
private static TestDo _instance = new TestDo();
public static TestDo getInstance(){
return _instance;
}

//private ArrayList keys = new ArrayList();
/*
* 用ArrayList会出现两个结果和一个错误
* begin1417917694
* 结果1
3:3:1417917695
1:1:1417917695
4:4:1417917695
1:2:1417917696
结果2
begin1417917815
3:3:1417917816
1:2:1417917816
1:1:1417917816
4:4:1417917816
ERROR
不能在遍历ArrayList的时候,对ArrayList进行添加或者删除
换用CopyOnWriteArrayList
发现还是会出现两个结果,结果如上所示。不明白了???
*
*/
CopyOnWriteArrayList keys = new CopyOnWriteArrayList();
public void doSome(Object key,String value){
Object o = key;
if(!keys.contains(o)){
keys.add(o);
}else{

for(Iterator iter=keys.iterator();iter.hasNext();){
try {
Thread.sleep(20);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Object oo = iter.next();
if(oo.equals(o)){
o = oo;
break;
}
}
}
//以大括号内的是需要局部同步的代码,不能改动

synchronized(o)
{
try {
Thread.sleep(1000);
System.out.println(key+":"+value+":"
+(System.currentTimeMillis()/1000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: