Java的线程编程很是简单。但有时会看到一些关于线程的错误用法。下面列出一些应该注重的问题。! S+ d6 V7 v. F' L8 y" G
1.同步对象的恒定性
$ E; n) m! Z; L All java objects are references.
. X% ]1 l3 A/ {8 ^' W 对于局部变量和参数来说,java琅缦沔的int, float, double, boolean等根基数据类型,都在栈上。这些根基类型是无法同步的;java琅缦沔的对象(根对象是Object),全都在堆里,指向对象的reference在栈上。
: M) p* a" K/ l& i; b( l) M java中的同步对象,现实上是对于reference所指的“对象地址”进行同步。2 G. q) A; }+ X- v; n
需要注重的问题是,万万不要对同步对象年夜头赋值。举个例子。& e; w; p9 h# K9 M
class A implements Runnable! O w( ]: x& h( v! ?8 m' F( U
}" t7 K% \6 Q. p# S" ]
}8 o+ [$ \5 K4 t* B# t# g7 `! O
}
! |5 V6 a# m$ \4 Z run函数琅缦沔的这段同步代码现实上是毫无意义的。因为每一次lock都给年夜头分配了新的对象的reference,每个线程都在新的reference同步。
& [+ K" Y& h& Z* Z 巨匠可能感受稀疏,怎么会举这么一个例子。因为我见过这样的代码,同步对象在其它的函数里被年夜头赋了新值。$ s. X6 r/ ^8 _5 x4 T
这种问题很难查出来。所以,一般应该把同步对象声明为final.
2 ~# R' n' K! u( ~, ?0 s final Object lock = new Object;7 n; s* ^0 ^5 U$ l: O$ M
使用Singleton Pattern 设计模式来获取同步对象,也是一种很好的选择。* i$ @' _7 C' C0 R/ J
2.若何放置共享数据
{, t& S$ \( u' { 实现线程,有两种体例,一种是继续Thread类,一种是实现Runnable接口。
3 q+ T) h$ U7 j2 q4 D9 B# R 膳缦沔举的例子,采用实现Runnable接口的体例。本文举荐这种体例。" P! k! U- x" N4 O1 N: k5 E2 t
首先,把需要共享的数据放在一个实现Runnable接口的类琅缦沔,然后,把这个类的实例传给多个Thread的机关体例。这样,新建树的多个Thread,都配合拥有一个Runnable实例,共享统一份数据。5 `: `$ l' L' W7 C# }
假如采用继续Thread类的体例,就只好使用static静态成员了。假如共享的数据斗劲多,就需要年夜量的static静态成员,令轨范数据结构杂乱,难以扩展。这种情形应该尽量避免。( Q% z6 a2 l" `6 s
编写一段多线程代码,措置一个稍微复杂点的问题」现体例的口角,一试便知。
; C5 v: l1 Y* X/ Y# R, M( ]6 E0 R) \ 3.同步的粒度
( [. N4 c# ~9 K 线程同步的粒度越小越好,即,线程同步的代码块越小越好。尽量避免用synchronized润色符来声明体例。尽量使用synchronized的体例,假如不想惹人新的同步对象,使用synchronized的体例。而且,synchronized代码块越小越好。 </p> public static int maxSubSum3( int [ ] a )
/ G. O( A& U: }* r4 n3 I ` {
3 o1 v; ^) W) ~: d* z: k' y int maxSum = 0;) a3 y4 O, V6 t0 h8 G. y9 u% \
int thisSum = 0;
" w( e; S! Y% |1 X1 X for( int i = 0, j = 0; j < a.length; j++ )
: o9 e( k, P' r _' g {8 P3 X; ^5 O' O) m2 S" T
thisSum += a[ j ];! `4 b( e6 w; F l2 Y6 ~
if( thisSum > maxSum )
4 l& [* T6 u( S% o+ I B {
7 k; L5 K- p/ @( I maxSum = thisSum;
% E# i4 e4 _ G: q seqStart = i;3 A' w6 h K5 C6 d' \
seqEnd = j;3 W4 f5 s0 ?+ V( Q& J. B, A
} x2 F' N: u9 Z
else if( thisSum < 0 )
$ w* b- {4 u( Y, j, r! c {
3 N( l2 G- ?( w: V i = j + 1;
' K" n2 B( E: R- K$ N7 } thisSum = 0;+ u) q; Y( p$ P
}5 Y& Y( q; r+ i' v
}6 V! q& l- t2 ?1 a1 n+ X Y' _
return maxSum;
! n* ?( e) h% a/ B) k \2 n( J }2 e- @! F- }' j/ B' E
/**. j1 c+ ^% U5 e. f# {. f- Y
* Recursive maximum contiguous subsequence sum algorithm.
; W1 H9 r; B& B. t5 U * Finds maximum sum in subarray spanning a[left..right].
/ g/ m9 ?+ Y" @$ {: ~ * Does not attempt to maintain actual best sequence.
$ K, N* y* }& | */
9 T# Y2 o1 \0 {) V; K private static int maxSumRec( int [ ] a, int left, int right )2 c6 K. E& `8 f% j4 J
{
" f, z: F4 D4 M% b/ V- A int maxLeftBorderSum = 0, maxRightBorderSum = 0;1 ~5 ?8 r4 q" u5 B$ \$ D
int leftBorderSum = 0, rightBorderSum = 0;3 E, q7 q' T2 l; I; K
int center = ( left + right ) / 2;# `, |8 B1 _+ M0 Q/ O
if( left == right ) // Base case1 _# I9 B/ _4 [1 A5 N. q9 D
return a[ left ] > 0 ? a[ left ] : 0;$ ]2 T$ Y% Q* t L8 _
int maxLeftSum = maxSumRec( a, left, center );
9 x& s- R: X. W& [3 m int maxRightSum = maxSumRec( a, center + 1, right );1 ]! r- X( X9 m& a0 I
for( int i = center; i >= left; i– )
% ^( l# p" o/ V {
2 V' h6 U0 G8 X leftBorderSum += a[ i ];% P7 V+ q* k8 c5 @8 w
if( leftBorderSum > maxLeftBorderSum )
9 z, E) O: B2 {2 @# [ maxLeftBorderSum = leftBorderSum;
# Z$ G4 ]1 V8 G# d9 V: R& m }- P2 N5 d% [( i$ [
for( int i = center + 1; i maxRightBorderSum )0 q4 p, W* @+ k) |. Z1 y3 P
maxRightBorderSum = rightBorderSum;
% p: x4 S6 w4 X. e+ ^7 z6 |3 k6 ` l }2 L9 ]$ n) B3 I7 f# [
return max3( maxLeftSum, maxRightSum,+ j/ n5 A1 [" F. N' y1 h# u( K% q
maxLeftBorderSum + maxRightBorderSum );
4 J: e( t8 j' q! j9 ?7 A }, o4 a' m6 }" A5 V+ g2 T
/**
6 r0 H6 F8 P/ G0 D X( ~ * Return maximum of three integers.: M1 R, W" d' q0 L: G0 F _6 H
*/7 K4 Y7 k& U" V( E* Q8 B8 l
private static int max3( int a, int b, int c )
$ ~+ h+ p. I" C {4 B: a+ Y# d& M( q
return a > b ? a > c ? a : c : b > c ? b : c;# Q/ W/ A i2 x1 g
}
6 k* e- Z( b* Z r. z) a$ H /**
7 e, y5 H% j: \% C0 v * Driver for divide-and-conquer maximum contiguous# D |# B( y9 K. `1 b
* subsequence sum algorithm.& k0 W! R2 Z+ W6 m2 w8 T- v
*/
; A& s v) c* o public static int maxSubSum4( int [ ] a )
/ T+ `2 \6 j5 R5 |, K+ B# b {
# T; {, I" i$ f6 A2 H! ^ return a.length > 0 ? maxSumRec( a, 0, a.length - 1 ) : 0;
7 d' g4 [2 G6 l }: t6 y* d' ^: u0 J, Y# g+ B
public static void getTimingInfo( int n, int alg )
4 z3 N4 t6 R# @ i {
$ T P' l3 R/ O9 H int [] test = new int[ n ];! b( s1 G$ ~/ u+ f
long startTime = System.currentTimeMillis( );;
- q* A5 I" @7 A6 f2 T long totalTime = 0;
9 l Q. O/ S/ |* P int i;5 r, ^7 n. {5 {2 d6 @
for( i = 0; totalTime < 4000; i++ )- b/ S1 |$ d5 S- ]
{
/ w! G+ d/ w6 ~! a for( int j = 0; j < test.length; j++ )
, p& w6 {8 p+ r+ V( H test[ j ] = rand.nextInt( 100 ) - 50;1 ^ N: u9 o4 V+ g \
switch( alg )8 [& W ^$ B- E
{% |" G- N; s* ?3 D/ r$ _; q, h
case 1:
/ G) {4 [* f4 R" W" M maxSubSum1( test );. Z; h! z4 f3 y2 g% t0 A
break;; w. F2 x0 Y! H9 o* w& I
case 2:
% m8 R$ }, E7 D, ^! r maxSubSum2( test );
. b6 q! p( p2 I/ T* {5 Z$ N: g break;
s$ e6 I; }# B1 V: c! o case 3:6 o9 i5 Z( Z+ T
maxSubSum3( test );
) F5 x# s8 }) [3 V( V1 h$ g break;
; j2 {. j% N+ K. ?& \# E8 X case 4:" J `% u$ Q# W6 J/ e a
maxSubSum4( test );7 u3 \8 m7 H. Z! }5 `+ |
break;
% Z+ \ @" f& B3 y: Q0 h4 w# V& A }2 o4 d0 C' \) A$ O
totalTime = System.currentTimeMillis( ) - startTime;8 o0 B* {& E; K F3 r1 O4 I! g
}$ n" r. }9 u: r# n
System.out.println( ”Algorithm #” + alg + ”t”
2 e7 B( }5 k. a# V' e) j( B6 T + ”N = ” + test.length; V. d* y, |3 H6 E( z9 B
+ ”ttime = ” + ( totalTime * 1000 / i ) + ” microsec” );' h w6 L4 i* k* G! r
}8 O0 s: g. V$ o+ ]2 a
private static Random rand = new Random( );
% I. ~" @% _9 r2 o: l2 `& T /**: D- Q! u5 S, B6 D: d) b
* Simple test program.3 x& @2 @& h3 A$ F7 X, O, X- r$ d
*/
/ q$ |. }- o( }4 h public static void main( String [ ] args ): Z3 B, u$ y7 X( e4 K
{. F0 I- k; _( i& o/ X+ ^! `3 A
int a[ ] = { 4, -3, 5, -2, -1, 2, 6, -2 };+ H3 t' e" o" a
int maxSum;
" ?" s- q @7 D/ E! X3 @# r maxSum = maxSubSum1( a );1 ?& ]: r: h+ r7 X; i
System.out.println( ”Max sum is ” + maxSum + ”; it goes”
0 i: I/ q) z& v0 ?6 @/ O7 j + ” from ” + seqStart + ” to ” + seqEnd );& e1 c% E- t# m9 p" k1 x1 W! ~
maxSum = maxSubSum2( a );
( f$ F6 e& x. _5 U) ]' U System.out.println( ”Max sum is ” + maxSum + ”; it goes”
. l- z6 d6 u+ f# H( Z+ @ + ” from ” + seqStart + ” to ” + seqEnd );
# w5 ?0 n8 @" h( w maxSum = maxSubSum3( a );
' d4 R3 R% ]0 K System.out.println( ”Max sum is ” + maxSum + ”; it goes”
, \5 u7 M, f$ h' k7 E# i + ” from ” + seqStart + ” to ” + seqEnd );
; b" E4 \' a5 o+ l1 i: _' s! N maxSum = maxSubSum4( a );! b$ o$ ^) |& k; [
System.out.println( ”Max sum is ” + maxSum );( I% G7 _+ K# `: o
// Get some timing info
6 N0 z- J/ U! e for( int n = 10; n = 1; alg– )
* h% ^/ D& r, V {
5 K" A4 m7 U$ [1 Y1 K3 i8 ^ if( alg == 1 && n > 50000 )
3 Y. }& X0 f+ Q, v' z continue;; ]- t1 Z! F' j; @) t# v
getTimingInfo( n, alg );/ _! `1 T) _# e7 ]2 z4 m
}3 ^; k6 K- q2 @$ n3 ]5 [4 e
}) O- I6 L# B9 O- r
} |