主程序运行1000个子线程(太少了结果不容易出来),每个子线程执行指向同一整数引用的i++,当1000个子线程运行完毕后,主线程继续运行,输出最终的i值。很显然,如果最终输出的结果i值不等于1000,那么中间i++操作一定被分解了。程序代码如下:
【版本一】
import cn.yuzhe.multi.util.AllFinished;


public class ThreadSafeClass
{


public static void main(String[] args)
{
//要创建的子线程数
int threadNum=1000;
//每个子线程都要引用的对象
A_Integer bb=new A_Integer();
//创建能判断所有子线程是否结束的对象,用于保证主线程能在多有子线程都结束后再执行余下的代码,
//防止主线程提前于子线程结束
AllFinished af=new AllFinished(threadNum);
//创建多个子线程对象
NoAtomicIntegerThread[] at=new NoAtomicIntegerThread[threadNum];

for(int i=0;i<threadNum;i++)
{
at[i]=new NoAtomicIntegerThread(bb,i,af);
}

for(int i=0;i<threadNum;i++)
{
at[i].start();
}

while(true)
{

if( af.isAllFinished() )
{
System.out.println("主线程运行结束,应该获得的最终值为"+threadNum
+";实际最终值为"+bb.int_I);
break;
}
int sleep=500; //睡眠一段时间,释放时间片

try
{
Thread.sleep(sleep);

} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}


class NoAtomicIntegerThread extends Thread
{
public A_Integer jj;
private int id;
private AllFinished af;


public void run()
{
jj.int_I++;
af.setItemFinished(id);
// System.out.println(jj.int_I); //输出中间结果
}


public NoAtomicIntegerThread(A_Integer __j,int _id,AllFinished _af)
{
super();
this.jj=__j;
this.id=_id;
this.af=_af;
}
}

class A_Integer


{
public int int_I=0;
}


这里要用到一个我自己定义的util类:

/** *//**
* @author 红楼无梦,JAVA多线程QQ群:34237757
* Date:2008-8-13 09:28
* Function: 主线程创建多个分线程,保证主线程在所有分线程都结束后才能运行余下的代码,直至结束。
*/

public class AllFinished
{
private boolean[] isItemsFinished;
private int num;


public AllFinished(int itemNum)
{
super();
num=itemNum;
isItemsFinished=new boolean[num];
for(int i=0;i<num;i++)
isItemsFinished[i]=false;
}

public synchronized boolean setItemFinished(int i)

{
if(i>=num)
return false;
this.isItemsFinished[i]=true;
return true;
}

public synchronized boolean isAllFinished()

{

for(int i=0;i<num;i++)
{
if(!this.isItemsFinished[i])
return false;
}
return true;
}
}

例子需要运行多次才能看到结果,当实际结果和理想结果不一样的时候,很显然,i++被分解了,结果的部分输入如下:
......
996
997
998
主线程运行结束,应该获得的最终值为1000;实际最终值为998。
=====================================================
【改进一】下面的代码用AtomicInteger进行了改进,使得i++操作被原子化,代码如下:

public class ThreadSafeClass
{


public static void main(String[] args)
{
//要创建的子线程数
int threadNum=1000;
//每个子线程都要引用的对象
AtomicInteger bb=new AtomicInteger(0);
//创建能判断所有子线程是否结束的对象,用于保证主线程能在多有子线程都结束后再执行余下的代码,
//防止主线程提前于子线程结束
AllFinished af=new AllFinished(threadNum);
//多个子线程对象
AtomicIntegerThread[] at=new AtomicIntegerThread[threadNum];

for(int i=0;i<threadNum;i++)
{
at[i]=new AtomicIntegerThread(bb,i,af);
}

for(int i=0;i<threadNum;i++)
{
at[i].start();
}

while(true)
{

if(af.isAllFinished())
{
System.out.println("主线程运行结束,应该获得的最终值为"+threadNum
+";实际最终值为"+bb);
break;
}
int sleep=(int)(Math.random()*500);

try
{
Thread.sleep(sleep);

} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}


class AtomicIntegerThread extends Thread
{
private int id;
private AllFinished af;
public AtomicInteger j;


public AtomicIntegerThread(AtomicInteger __j,int _id,AllFinished _af)
{
super();
this.j=__j;
this.id=_id;
this.af=_af;
}



public void run()
{
j.getAndIncrement();
af.setItemFinished(id);
System.out.println(j); //这里输出没有同步,很可能会出现不一致,这里仅仅用来测试一下,正好能证明线程将操作分解^_^
}
}


运行了多次没有出现被分解的情况,最后我把线程数从一千改成一万,又增加到十万,并且运行多次,没有出现结果和预计结果不一致的情况。十万个线程啊!如果能分解的话早把程序分得七零八碎了,呵呵。某次结果如下:
......
99994
99993
99992
主线程运行结束,应该获得的最终值为100000;实际最终值为100000
=====================================================
【改进二】群友TITAN的方法更简单,在版本一的基础上加上一小段代码

class NoAtomicIntegerThread extends Thread
{





public void run()
{

synchronized(jj)
{
jj.int_I++;
}
af.setItemFinished(id);
System.out.println(jj.int_I);
}




}


我对比了一下改进一和改进二,在十万个线程并发情况下,二者的运行速度几乎没有差别。可见JAVA类库中的AtomicInteger还是很实用的。
大伙有什么改进的方法,欢迎大家提意见。yuzhe80@126.com
******************************************************************************
后话:这里为了保证主线程在子线程都执行完后再继续执行,特意定义了一个类AllFinished,记录每个子线程是否结束,其实大可不必,因为JAVA中对线程有join函数,在main函数中改成这样就可以了。

public class ThreadSafeClass
{

public static void main(String[] args)
{
//要创建的子线程数
int threadNum=1000;
//每个子线程都要引用的对象
AtomicInteger bb=new AtomicInteger(0);
//多个子线程对象
AtomicIntegerThread[] at=new AtomicIntegerThread[threadNum];

for(int i=0;i<threadNum;i++)
{
at[i]=new AtomicIntegerThread(bb,i);
}
long last=System.currentTimeMillis();

for(int i=0;i<threadNum;i++)
{
at[i].start();
}

for(int i=0;i<threadNum;i++)
{

try
{
at[i].join(); //保证主线程在所有子线程结束后再执行

} catch (InterruptedException e)
{
e.printStackTrace();
}
}
System.out.println("主线程运行结束,应该获得的最终值为"+threadNum
+";实际最终值为"+bb+"程序运行时间"+(System.currentTimeMillis()-last)+"毫秒");

}
}


而且这样修改,在性能上有很大提升,用我自定义的类AllFinished,运行1000个线程,平均时间为2100ms,而用join函数,平均时间为1600ms,性能提升了25%。以后还是推荐大伙使用join吧^_^