JAVA认证:JavaThread应注意的技巧
Java的线程编程很是简单。但有时会看到一些关于线程的错误用法。下面列出一些应该注重的问题。1.同步对象的恒定性
All java objects are references.
对于局部变量和参数来说,java琅缦沔的int, float, double, boolean等根基数据类型,都在栈上。这些根基类型是无法同步的;java琅缦沔的对象(根对象是Object),全都在堆里,指向对象的reference在栈上。
java中的同步对象,现实上是对于reference所指的“对象地址”进行同步。
需要注重的问题是,万万不要对同步对象年夜头赋值。举个例子。
class A implements Runnable
}
}
}
run函数琅缦沔的这段同步代码现实上是毫无意义的。因为每一次lock都给年夜头分配了新的对象的reference,每个线程都在新的reference同步。
巨匠可能感受稀疏,怎么会举这么一个例子。因为我见过这样的代码,同步对象在其它的函数里被年夜头赋了新值。
这种问题很难查出来。所以,一般应该把同步对象声明为final.
final Object lock = new Object;
使用Singleton Pattern 设计模式来获取同步对象,也是一种很好的选择。
2.若何放置共享数据
实现线程,有两种体例,一种是继续Thread类,一种是实现Runnable接口。
膳缦沔举的例子,采用实现Runnable接口的体例。本文举荐这种体例。
首先,把需要共享的数据放在一个实现Runnable接口的类琅缦沔,然后,把这个类的实例传给多个Thread的机关体例。这样,新建树的多个Thread,都配合拥有一个Runnable实例,共享统一份数据。
假如采用继续Thread类的体例,就只好使用static静态成员了。假如共享的数据斗劲多,就需要年夜量的static静态成员,令轨范数据结构杂乱,难以扩展。这种情形应该尽量避免。
编写一段多线程代码,措置一个稍微复杂点的问题」现体例的口角,一试便知。
3.同步的粒度
线程同步的粒度越小越好,即,线程同步的代码块越小越好。尽量避免用synchronized润色符来声明体例。尽量使用synchronized的体例,假如不想惹人新的同步对象,使用synchronized的体例。而且,synchronized代码块越小越好。 </p> public static int maxSubSum3( int [ ] a )
{
int maxSum = 0;
int thisSum = 0;
for( int i = 0, j = 0; j < a.length; j++ )
{
thisSum += a[ j ];
if( thisSum > maxSum )
{
maxSum = thisSum;
seqStart = i;
seqEnd = j;
}
else if( thisSum < 0 )
{
i = j + 1;
thisSum = 0;
}
}
return maxSum;
}
/**
* Recursive maximum contiguous subsequence sum algorithm.
* Finds maximum sum in subarray spanning a.
* Does not attempt to maintain actual best sequence.
*/
private static int maxSumRec( int [ ] a, int left, int right )
{
int maxLeftBorderSum = 0, maxRightBorderSum = 0;
int leftBorderSum = 0, rightBorderSum = 0;
int center = ( left + right ) / 2;
if( left == right )// Base case
return a[ left ] > 0 ? a[ left ] : 0;
int maxLeftSum= maxSumRec( a, left, center );
int maxRightSum = maxSumRec( a, center + 1, right );
for( int i = center; i >= left; i– )
{
leftBorderSum += a[ i ];
if( leftBorderSum > maxLeftBorderSum )
maxLeftBorderSum = leftBorderSum;
}
for( int i = center + 1; imaxRightBorderSum )
maxRightBorderSum = rightBorderSum;
}
return max3( maxLeftSum, maxRightSum,
maxLeftBorderSum + maxRightBorderSum );
}
/**
* Return maximum of three integers.
*/
private static int max3( int a, int b, int c )
{
return a > b ? a > c ? a : c : b > c ? b : c;
}
/**
* Driver for divide-and-conquer maximum contiguous
* subsequence sum algorithm.
*/
public static int maxSubSum4( int [ ] a )
{
return a.length > 0 ? maxSumRec( a, 0, a.length - 1 ) : 0;
}
public static void getTimingInfo( int n, int alg )
{
int [] test = new int[ n ];
long startTime = System.currentTimeMillis( );;
long totalTime = 0;
int i;
for( i = 0; totalTime < 4000; i++ )
{
for( int j = 0; j < test.length; j++ )
test[ j ] = rand.nextInt( 100 ) - 50;
switch( alg )
{
case 1:
maxSubSum1( test );
break;
case 2:
maxSubSum2( test );
break;
case 3:
maxSubSum3( test );
break;
case 4:
maxSubSum4( test );
break;
}
totalTime = System.currentTimeMillis( ) - startTime;
}
System.out.println( ”Algorithm #” + alg + ”t”
+ ”N = ” + test.length
+ ”ttime = ” + ( totalTime * 1000 / i ) + ” microsec” );
}
private static Random rand = new Random( );
/**
* Simple test program.
*/
public static void main( String [ ] args )
{
int a[ ] = { 4, -3, 5, -2, -1, 2, 6, -2 };
int maxSum;
maxSum = maxSubSum1( a );
System.out.println( ”Max sum is ” + maxSum + ”; it goes”
+ ” from ” + seqStart + ” to ” + seqEnd );
maxSum = maxSubSum2( a );
System.out.println( ”Max sum is ” + maxSum + ”; it goes”
+ ” from ” + seqStart + ” to ” + seqEnd );
maxSum = maxSubSum3( a );
System.out.println( ”Max sum is ” + maxSum + ”; it goes”
+ ” from ” + seqStart + ” to ” + seqEnd );
maxSum = maxSubSum4( a );
System.out.println( ”Max sum is ” + maxSum );
// Get some timing info
for( int n = 10; n = 1; alg– )
{
if( alg == 1 && n > 50000 )
continue;
getTimingInfo( n, alg );
}
}
}
页:
[1]