传入Thread的都是ArrayList除了最后一个s是String
在每个Thread进行处理时都需要s来进行判断而且都会在s里附加文本
我的想法是用以下的方法是不是可行
但有一个问题是传入时s是""会不会同样二个进程同时抓到""那就会有问题
该如何避免这种问题?
String s="";
LoopThread lt01=new LoopThread(al1,al2,al3,al4,al5,al6,al7,al8,al9,al10,bomal2,al11,s );
lt01.start();
LoopThread lt02=new LoopThread(al2,al3,al4,al5,al6,al7,al8,al9,al10,al1,bomal2,al11,s );
lt02.start();
LoopThread lt03=new LoopThread(al3,al4,al5,al6,al7,al8,al9,al10,al1,al2,bomal2,al11,s );
lt03.start();
LoopThread lt04=new LoopThread(al4,al5,al6,al7,al8,al9,al10,al1,al2,al3,bomal2,al11,s );
lt04.start();
LoopThread lt05=new LoopThread(al5,al6,al7,al8,al9,al10,al1,al2,al3,al4,bomal2,al11,s );
lt05.start();
LoopThread lt06=new LoopThread(al6,al7,al8,al9,al10,al1,al2,al3,al4,al5,bomal2,al11,s );
lt06.start();
LoopThread lt07=new LoopThread(al7,al8,al9,al10,al1,al2,al3,al4,al5,al6,bomal2,al11,s );
lt07.start();
LoopThread lt08=new LoopThread(al8,al9,al10,al1,al2,al3,al4,al5,al6,al7,bomal2,al11,s );
lt08.start();
LoopThread lt09=new LoopThread(al9,al10,al1,al2,al3,al4,al5,al6,al7,al8,bomal2,al11,s );
lt09.start();
LoopThread lt10=new LoopThread(al10,al1,al2,al3,al4,al5,al6,al7,al8,al9,bomal2,al11,s );
lt10.start();
在每个Thread进行处理时都需要s来进行判断而且都会在s里附加文本
我的想法是用以下的方法是不是可行
但有一个问题是传入时s是""会不会同样二个进程同时抓到""那就会有问题
该如何避免这种问题?
String s="";
LoopThread lt01=new LoopThread(al1,al2,al3,al4,al5,al6,al7,al8,al9,al10,bomal2,al11,s );
lt01.start();
LoopThread lt02=new LoopThread(al2,al3,al4,al5,al6,al7,al8,al9,al10,al1,bomal2,al11,s );
lt02.start();
LoopThread lt03=new LoopThread(al3,al4,al5,al6,al7,al8,al9,al10,al1,al2,bomal2,al11,s );
lt03.start();
LoopThread lt04=new LoopThread(al4,al5,al6,al7,al8,al9,al10,al1,al2,al3,bomal2,al11,s );
lt04.start();
LoopThread lt05=new LoopThread(al5,al6,al7,al8,al9,al10,al1,al2,al3,al4,bomal2,al11,s );
lt05.start();
LoopThread lt06=new LoopThread(al6,al7,al8,al9,al10,al1,al2,al3,al4,al5,bomal2,al11,s );
lt06.start();
LoopThread lt07=new LoopThread(al7,al8,al9,al10,al1,al2,al3,al4,al5,al6,bomal2,al11,s );
lt07.start();
LoopThread lt08=new LoopThread(al8,al9,al10,al1,al2,al3,al4,al5,al6,al7,bomal2,al11,s );
lt08.start();
LoopThread lt09=new LoopThread(al9,al10,al1,al2,al3,al4,al5,al6,al7,al8,bomal2,al11,s );
lt09.start();
LoopThread lt10=new LoopThread(al10,al1,al2,al3,al4,al5,al6,al7,al8,al9,bomal2,al11,s );
lt10.start();
1、你想干的事情绝对不可能实现;
2、你想干的事情绝对没有并发问题。
所以,线程里面对String的操作,按楼主的写法,貌似传不出来。
如果楼主要共享String的内容,可以写成线程的静态变量;或者,使用StringBuffer对象。
所以我想是否在Thread里建个static变量就可以使用?
◎ 总的来说,情况是:
lt01 = new LoopThread(al1,al2,al3,al4,al5,al6,al7,al8,al9,al10,bomal2,al11,s);
lt02 = new LoopThread(al2,al3,al4,al5,al6,al7,al8,al9,al10,al1,bomal2,al11,s);你在lt01里面,无论对s做什么事情,lt02也不知道(当然,那种用反射去直接操数据结构的除外)。
因为lt01中s形参,跟lt02中s形参,就是毫无关系的两个变量,虽然它们在刚进入函数的时候指向同一个String实例。
◎ 所以我想是否在Thread里建个static变量就可以使用?
可以,LoopThread 里面有个static变量的话,所有实例都引用一个变量了。但将面临资源并发访问的问题。建议这样:
1、写一个类,比如名叫:SharedString,代替你原来的String参数;
2、SharedString中维护一个private 的 StringBuffer;
3、SharedString根据你LoopThread的操作需要,提供一组函数,并全部加上 synchronized;
4、严格注意函数必须是自完备的,也不要出现LoopThread代码中把一个函数的返回结果传给另一个函数,这就破坏了synchronized能保护的边界,比如:
SharedString ss = new SharedString();
ss.set(ss.get() + "asdf"); // 超猪头做法
public void run()
{
s.wait();
...
s.notify();
}
这样就不会出现s被两个线程同时修改的情况了
public synchronized static String sappend(String filter,String s1,String s2){
filter=filter+s1+"$"+s2+";";
return filter;
}
public class Test
{
public static void main(String[] args)
{
StringBuilder s = new StringBuilder();
Object lock = new Object();
for (int i = 0; i < 10; i++)
{
new TestThread(i, s, lock).start();
}
}
}class TestThread extends Thread
{
private int i; //线程编号
private StringBuilder s; //要处理的字符串
private Object lock; //互斥的工具
public TestThread(int i, StringBuilder s, Object lock)
{
this.i = i;
this.s = s;
this.lock = lock;
}
public void run()
{
while (true)
{
synchronized (lock)
{
s.append(i); //将自己的编号添加到字符串中
System.out.println(s); //打印这个字符串被哪些线程调用过
}
try
{
Thread.sleep(1000); //这里停一秒为了便于观察结果
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
虽然你企图用synchronized解决并发问题,但LoopThread的几个实例准备怎么共享filter?如果是直接 static String filter 的话, 那么这个函数的参数和return就显得多余了,而且增加危险性。
这种做法是可以的;不过可以直接点,不创建新类,也可以这样了: set(get() + "asdf"); // 超猪头做法
传递一个ArrayList<String> aList代替s;
再在LoopThread中加个方法:ArrayList<String> aList = new ArrayList<String>(1)
aList.add(s);
new LoopThread(...,aList);...LoopThread中:
ArrayList<String> aList = 传递来的aList;
public void changeValue(){
synchronized(aList){
aList.set(0, aList.get(0) + "asdf");
}
}
因为我会起15个Thread但希望这个lock是共用且可以新增所以可以改成以下这样?
private static Object lock; //互斥的工具
其他都和你写的相同
意思是说,可能容易被误用,而导致脱离了Synchronized的控制范围,比如:
LoopThread {
private static String a;
public void run() {
a = sappend(a, s1, s2); // 这句话就已经脱离了synchronized控制范围,有并发问题
} public synchronized static String sappend(String filter,String s1,String s2){
filter=filter+s1+"$"+s2+";";
return filter;
}
}
一般来说,从设计严谨性出发,应该消除所有可能被误用的口子;尤其是如果这个程序可能是协作开发的情况下,未必每一个人都能理解你的原始设计意图;这也是为什么我建议专门定义 SharedString 去维护这种关键资源。