1.synchronize
做用在靜態方法上和作用在代碼塊上(鎖對象是類名.class)效果一樣
public class SynThread1{
public static void main(String[] args) {
new Thread() {
public void run() {
print1();
};
}.start();
new Thread() {
public void run() {
print2();
};
}.start();
}
public static synchronized void print1() {
for(int i=0;i<5;i++) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.print(i+" ");
}
System.out.println();
}
public static void print2() {
synchronized (SynThread1.class) {
for(int i=5;i<10;i++) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.print(i+" ");
}
System.out.println();
}
}
}
結果
2.ReentrantLock重入鎖
lock()方法加鎖,unlock()釋放鎖。建議unlock()在finally語句塊中。
public class LockThread1 {
static ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
print1();
}
}).start();
new Thread() {
public void run() {
print2();
};
}.start();
}
public static void print1() {
for(int i=1;i<5;i++) {
lock.lock();
try {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.print(i);
}finally {
lock.unlock();
}
}
}
public static void print2() {
for(int i=5;i<9;i++) {
lock.lock();
try {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.print(i);
}finally {
lock.unlock();
}
}
}
}
結果
3.可能會同步的volatile
每次要線程要訪問volatile修飾的變量時都是從內存中讀取,而不是存緩存當中讀取,因此每個線程訪問到的變量值都是一樣的。但是它不保證同步,只是接近而已。運行了10次,其中8次同步。
public class VolThread1 {
volatile static int a = 0;
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
add1();
System.out.println(a);
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
add2();
System.out.println(a);
}
}).start();
}
public static void add1() {
for(int i=1;i<=10;i++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
a = a+i;
}
}
public static void add2() {
for(int i=1;i<=10;i++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
a = a+i;
}
}
}
正常結果
其中一個異常結果
不推薦的方法
4.Semaphore信號量(可參數設置幾個線程同時運行)
new Semaphore(int permits)參數是允許同時進行的線程數,如果線程未獲得准入許可,進入等待,acquire()方法嘗試獲得許可,release()方法釋放一個許可
public class SemThread1 {
//控制同時運行的線程數
final static Semaphore semap = new Semaphore(2);
public static void main(String[] args) {
new Thread() {
public void run() {
print1();
};
}.start();
new Thread() {
public void run() {
print1();
};
}.start();
new Thread() {
public void run() {
print2();
};
}.start();
}
public static void print1() {
try {
semap.acquire();
for(int i=1;i<5;i++) {
TimeUnit.SECONDS.sleep(1);
System.out.print(i);
}
System.out.println();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
semap.release();
}
}
public static void print2() {
try {
semap.acquire();
for(int i=5;i<9;i++) {
TimeUnit.SECONDS.sleep(1);
System.out.print(i);
}
System.out.println();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
semap.release();
}
}
}
這裏的三個線程同時對多隻能運行兩個
結果
5.CountDownLatch門閂
new CountDownLatch(int count)指定門閂數,countDown()方法將門閂減一,await()方法等待門閂數減爲0。
public class LatchThread {
final static CountDownLatch latch = new CountDownLatch(1);
public static void main(String[] args) {
new Thread() {
public void run() {
print1();
};
}.start();
new Thread() {
public void run() {
print2();
};
}.start();
}
public static void print1() {
for(int i=1;i<5;i++) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.print(i);
}
latch.countDown();
System.out.println();
}
public static void print2() {
try {
latch.await();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
for(int i=5;i<9;i++) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.print(i);
}
System.out.println();
}
}
結果
6.FixedThreadPool定長線程池(多多少少算是吧)
Executors.newFixedThreadPool(int nThreads),nThreads指定可以有幾個線程同時運行,如果是1的話,也算是有同步的效果。。。execute(Runnable command)方法執行線程。超過指定的nThreads會進入阻塞隊列等待。
public class ExecutorThread {
static ExecutorService fixedThreadPool = Executors.newFixedThreadPool(1);
public static void main(String[] args) {
fixedThreadPool.execute(new Runnable() {
@Override
public void run() {
print1();
}
});
fixedThreadPool.execute(new Runnable() {
@Override
public void run() {
print2();
}
});
}
public static void print1() {
for(int i=1;i<5;i++) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.print(i);
}
System.out.println();
}
public static void print2() {
for(int i=5;i<9;i++) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.print(i);
}
System.out.println();
}
}
結果