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();
}
}
结果