Java的线程编程很是简单。但有时会看到一些关于线程的错误用法。下面列出一些应该注重的问题。. e- ?8 H2 g9 N; a( f1 C
1.同步对象的恒定性, P: q& u8 ~3 A9 X t D
All java objects are references.( ]3 T. o% k8 ^3 A7 z) I: a$ }
对于局部变量和参数来说,java琅缦沔的int, float, double, boolean等根基数据类型,都在栈上。这些根基类型是无法同步的;java琅缦沔的对象(根对象是Object),全都在堆里,指向对象的reference在栈上。
! [' v6 _+ B9 b3 |) Q! _1 ] java中的同步对象,现实上是对于reference所指的“对象地址”进行同步。
' I* b3 D+ o5 U0 ]7 m2 O 需要注重的问题是,万万不要对同步对象年夜头赋值。举个例子。7 ^2 F4 \' [* R' h4 V
class A implements Runnable
; P P; f4 N5 \/ J7 h. p }( J, s2 _# f5 x, u3 N8 b; |
}
! l7 \5 i8 `1 ^2 e2 q: |# [ f }3 E- `) i. j1 \ `
run函数琅缦沔的这段同步代码现实上是毫无意义的。因为每一次lock都给年夜头分配了新的对象的reference,每个线程都在新的reference同步。0 M& m m' H" n j
巨匠可能感受稀疏,怎么会举这么一个例子。因为我见过这样的代码,同步对象在其它的函数里被年夜头赋了新值。
8 c4 U2 V3 l8 T: m/ c4 ]6 d7 F9 ?5 F 这种问题很难查出来。所以,一般应该把同步对象声明为final.3 H/ D! Q& g7 d# \, ~! Z" s
final Object lock = new Object;+ w, g" X/ P* E! W" }0 ]4 @, I1 }7 k
使用Singleton Pattern 设计模式来获取同步对象,也是一种很好的选择。
0 s, L# q q& y$ w7 D1 z% d" a 2.若何放置共享数据
2 A3 P6 M. q) R% F- M# E 实现线程,有两种体例,一种是继续Thread类,一种是实现Runnable接口。
" T d y) o. k0 s0 s 膳缦沔举的例子,采用实现Runnable接口的体例。本文举荐这种体例。; z. l' h! ~) l& B2 l
首先,把需要共享的数据放在一个实现Runnable接口的类琅缦沔,然后,把这个类的实例传给多个Thread的机关体例。这样,新建树的多个Thread,都配合拥有一个Runnable实例,共享统一份数据。
# w/ d2 C" q5 S! V6 z7 A$ ? 假如采用继续Thread类的体例,就只好使用static静态成员了。假如共享的数据斗劲多,就需要年夜量的static静态成员,令轨范数据结构杂乱,难以扩展。这种情形应该尽量避免。' G4 O* w" t" ?# @6 Y: Q
编写一段多线程代码,措置一个稍微复杂点的问题」现体例的口角,一试便知。; f5 C( F3 c1 K' k4 A4 `; [0 B5 S
3.同步的粒度
" K% d) O5 T) E7 d! B& q! J! Q 线程同步的粒度越小越好,即,线程同步的代码块越小越好。尽量避免用synchronized润色符来声明体例。尽量使用synchronized的体例,假如不想惹人新的同步对象,使用synchronized的体例。而且,synchronized代码块越小越好。 </p> public static int maxSubSum3( int [ ] a )
8 ]" m6 n' T- o& j2 i {
% D+ X6 O. t6 J, X7 s+ m8 D int maxSum = 0;
$ M# G1 a5 t7 w' A+ n A int thisSum = 0;
- H0 O8 C* c/ \: ]) ^ for( int i = 0, j = 0; j < a.length; j++ ). O- }2 R# p: x' r# J0 m% N* w
{
; e/ Y9 Y2 D/ t( D, ~6 K/ o2 F thisSum += a[ j ];) y6 h6 y u9 t3 a. @
if( thisSum > maxSum )
9 t' M& C* L- X: x) A {
- Y2 m |; ~ g* E( R maxSum = thisSum;7 Z6 G3 b5 q- a j2 U
seqStart = i;! z/ k& m. M- u3 s
seqEnd = j;
; ]/ u& h! C- z0 j0 S/ I }; h. m" d U7 W3 U
else if( thisSum < 0 )) i; @/ i0 h& c2 b
{
) Q0 S* A0 }$ }; w i = j + 1;
; k4 y3 p, B3 h/ R6 {4 o thisSum = 0;) o; g: e7 ^3 F1 F0 T7 V" G4 G8 n
}
8 X. r$ s0 U6 c0 ~* f4 Q$ S- W }# W- F2 L* w% V$ m) Q2 Y6 D- ?
return maxSum;
3 S% \0 z# z+ L; N" w; v }
' V8 K( ~, H, C7 c4 e; R /**# G. A% F) h) T9 }
* Recursive maximum contiguous subsequence sum algorithm.9 h+ s) Y. n( R b
* Finds maximum sum in subarray spanning a[left..right].
8 X( J2 N2 k$ L& N5 I * Does not attempt to maintain actual best sequence.
* m2 i) Y9 B" o& u */3 P# k" h: \6 J6 Q k0 j. Z, E% c
private static int maxSumRec( int [ ] a, int left, int right )8 H+ ^2 v; M7 G3 d6 X" N+ T* I4 G
{
0 k# l5 h/ X0 w |& r int maxLeftBorderSum = 0, maxRightBorderSum = 0;
1 p% M- j# J. {+ b int leftBorderSum = 0, rightBorderSum = 0;9 R2 l, Q; b& O% C
int center = ( left + right ) / 2;* a( G6 H1 x4 P, z2 Y6 N
if( left == right ) // Base case5 H. }% J0 g* {% R, A- Z
return a[ left ] > 0 ? a[ left ] : 0;$ q% b0 B; \% C) `# R E
int maxLeftSum = maxSumRec( a, left, center );
: O& w! d! V ^/ ~+ S7 u int maxRightSum = maxSumRec( a, center + 1, right );
% o7 ]( i. z* u# u8 y3 m8 Z( F J4 b for( int i = center; i >= left; i– )
' r) V# S% z% m# o { z3 u2 d+ \6 K( t, R' i$ G
leftBorderSum += a[ i ];+ A& a+ J( D7 ^3 t; \" _
if( leftBorderSum > maxLeftBorderSum )/ i6 J1 Y% }' g! V5 A
maxLeftBorderSum = leftBorderSum;
$ ?7 {) [+ U8 s" A }
9 h5 w6 S( k, C: C' w for( int i = center + 1; i maxRightBorderSum )( I* g% F) O7 v0 a& F
maxRightBorderSum = rightBorderSum;
3 `+ m/ R2 G% [2 x- O1 C! a( b3 [ }; z& r- S0 E7 M3 T8 u5 W- F
return max3( maxLeftSum, maxRightSum,
- F! n% H% I6 q0 g( L maxLeftBorderSum + maxRightBorderSum );$ q' _1 N" Q, T; d. P* Y8 }
}
& h; m( T% I1 R: o c7 M /**" W" a6 m# T6 T0 t
* Return maximum of three integers.
8 |: m9 @8 Y' j6 N& ^. \& X */6 e+ D0 Y& Z8 G
private static int max3( int a, int b, int c )
4 G% p$ s/ ~6 u+ @ {# V% M0 q1 t: z) K) g$ |; _( z
return a > b ? a > c ? a : c : b > c ? b : c;: d7 {' b5 @3 c
}
`" t5 ]7 H' c2 m* O3 q /**3 I' b2 H% o5 k9 |# R3 S" r
* Driver for divide-and-conquer maximum contiguous
+ }; k+ E5 U3 L. T! g * subsequence sum algorithm.1 p# l& O W. q! a$ L' I2 `+ u" a
*/
7 `: y8 \) w# e, s0 ]3 T public static int maxSubSum4( int [ ] a )# i' N& L, J0 e+ V! ~
{
, Y1 Q/ o" x4 @9 X return a.length > 0 ? maxSumRec( a, 0, a.length - 1 ) : 0;% m" L$ [- f1 p" L- I* E
}! I/ a7 x; |9 u" w) K
public static void getTimingInfo( int n, int alg )
e5 h; b; n: `& C$ J( T Z {) [ k& E* [: K7 ^: _ B
int [] test = new int[ n ];
" L2 s$ M* V' b% \' l; e% D9 o long startTime = System.currentTimeMillis( );;+ E8 S+ E5 ~/ b! j9 _! |0 z9 X7 y
long totalTime = 0;
% k+ M3 D2 Z( N0 _- ` int i;2 N+ z# a0 ~- A
for( i = 0; totalTime < 4000; i++ )
. }+ X' p0 J( m+ ?6 o+ C& | {
- h2 z0 l0 A; s- ]2 m$ w( ]! t9 P for( int j = 0; j < test.length; j++ )- ^4 L( e5 ^3 N% M, N
test[ j ] = rand.nextInt( 100 ) - 50;+ c* _5 [- K/ M
switch( alg )& f% V" I, x6 R" O9 f( Z: o
{
5 a- U+ Q9 L- ^) t2 W3 c$ C$ Z case 1:% f: k1 o1 Y- G* A
maxSubSum1( test );' _; Z! I! t. l y, s s! ~
break;/ d& I$ d4 W6 o% v; h8 `" t
case 2:
5 \. \5 r/ x7 x, T maxSubSum2( test );
+ u+ [+ X: ~/ S break;4 c% c& P+ A3 c) ^4 I; E# i) G
case 3:
7 ]! d1 N2 j$ p! z5 d maxSubSum3( test );, b: d; ~4 ?# Z
break;. D% P* l4 l# p% f5 L7 ?
case 4:
/ M; k0 o; |9 n# }! Z maxSubSum4( test );; M, p# p- i5 Y! x% x& Z3 D0 j
break; P$ M) E) E. @! R- ^
}
% I6 k4 W2 ]) a" y h totalTime = System.currentTimeMillis( ) - startTime;
# \) S {! P" i' {$ o }
: A& O7 \3 E% l { System.out.println( ”Algorithm #” + alg + ”t”
: I/ ]; V% {" D; ~9 t8 m + ”N = ” + test.length
. Z4 e" x! c3 q; r6 t + ”ttime = ” + ( totalTime * 1000 / i ) + ” microsec” );
3 E# _, D: L; _5 y1 i! v }8 k) l8 a7 Y0 `* E% X
private static Random rand = new Random( );
2 u% R6 c- L0 K2 m /**8 a3 g- t* P& ~
* Simple test program.! l* ~8 i. b% a. h3 c9 b. v/ r* W
*/9 z& Q6 A3 ]; |% i. S
public static void main( String [ ] args )
2 \' p1 C+ w) P E8 T4 G0 n* q1 p0 z {: \, W1 {8 _! t# G
int a[ ] = { 4, -3, 5, -2, -1, 2, 6, -2 };5 d$ t7 s6 a( B U/ C
int maxSum;5 Q+ P, P! q: B5 l1 u2 i. ?
maxSum = maxSubSum1( a );; x6 Y: l4 R* I
System.out.println( ”Max sum is ” + maxSum + ”; it goes”
8 P; s! O# E3 D# | + ” from ” + seqStart + ” to ” + seqEnd );6 B3 \7 H! r( H5 ~& S# o
maxSum = maxSubSum2( a );% H9 A1 l# ^+ g" G& G- N ?2 W( M; Z8 a
System.out.println( ”Max sum is ” + maxSum + ”; it goes”
$ w" c5 }: X3 g6 } + ” from ” + seqStart + ” to ” + seqEnd );
$ A! n$ ?! l8 A. D/ j maxSum = maxSubSum3( a );" }1 W) t; c# e) U% i
System.out.println( ”Max sum is ” + maxSum + ”; it goes”
# p2 Y5 j1 _7 }8 X+ _ + ” from ” + seqStart + ” to ” + seqEnd );
; `" M2 y& X/ y maxSum = maxSubSum4( a );& ^3 ~' i( Q7 Y( N6 ?2 F
System.out.println( ”Max sum is ” + maxSum );4 w; Y5 Y* g3 D
// Get some timing info
$ r* O9 K# v0 }6 } for( int n = 10; n = 1; alg– )
2 r4 b$ c5 K- |! r4 O+ ~0 G7 p {* j6 K5 D2 n( }) ?9 C& U' x
if( alg == 1 && n > 50000 )
) b0 `+ Z) I' w1 u8 ?- ~ continue;+ x& J8 Z2 i% U# v9 w0 V9 ~ J" m
getTimingInfo( n, alg );
3 F) V# T g2 O2 X8 M }
6 U, I, F6 O+ W, O0 h }
4 j$ Z V* q9 H/ _7 F% ?7 A# m } |