实现多线程的互斥效果
第一种是通过sychronized与wait,notify,具体代码如下
public class TestThread {
public static boolean isF=false;
public static void main(String[] args) {
final Arth arth = new Arth();
new Thread(new Runnable(){
@Override
public void run() {
for(int i=0;i<10;i++){
arth.test1();
}
}
}).start();
new Thread(new Runnable(){
@Override
public void run() {
for(int i=0;i<10;i++){
arth.test2();
}
}
}).start();
}
static class Arth{
public synchronized void test1(){
while(isF){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int i=1;i<11;i++){
System.out.println("A "+Thread.currentThread().getName()+" "+i);
}
isF=true;
this.notify();
}
public synchronized void test2(){
while(!isF){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int i=1;i<21;i++){
System.out.println("B "+Thread.currentThread().getName()+i);
}
isF=false;
this.notify();
}
}
}
运行结果
A Thread-0 1
A Thread-0 2
A Thread-0 3
A Thread-0 4
A Thread-0 5
A Thread-0 6
A Thread-0 7
A Thread-0 8
A Thread-0 9
A Thread-0 10
B Thread-11
B Thread-12
B Thread-13
B Thread-14
B Thread-15
B Thread-16
B Thread-17
B Thread-18
B Thread-19
B Thread-110
B Thread-111
B Thread-112
B Thread-113
B Thread-114
B Thread-115
B Thread-116
B Thread-117
B Thread-118
B Thread-119
B Thread-120
A Thread-0 1
A Thread-0 2
A Thread-0 3
A Thread-0 4
A Thread-0 5
A Thread-0 6
A Thread-0 7
A Thread-0 8
A Thread-0 9
A Thread-0 10
B Thread-11
B Thread-12
第二种是通过Condition与ReentrantLock来实现,具体如下:
public class ThreadA2 extends Thread{
private MyService2 service;
public ThreadA2(MyService2 service) {
super();
this.service = service;
}
@Override
public void run() {
super.run();
for(int i=0;i<Integer.MAX_VALUE;i++){
service.set();
}
}
}
public class ThreadB2 extends Thread{
private MyService2 service;
public ThreadB2(MyService2 service) {
super();
this.service = service;
}
@Override
public void run() {
super.run();
for(int i=0;i<Integer.MAX_VALUE;i++){
service.get();
}
}
}
public class MyService2 {
private ReentrantLock lock=new ReentrantLock();
private Condition condition=lock.newCondition();
private boolean hasValue=false;
public void set(){
try {
lock.lock();
while(hasValue==true){
condition.await();
}
System.out.println("打印 11");
hasValue=true;
condition.signal();
} catch (Exception e) {
e.printStackTrace();
}finally{
lock.unlock();
}
}
public void get(){
try {
lock.lock();
while(hasValue==false){
condition.await();
}
System.out.println("复印 22");
hasValue=false;
condition.signal();
} catch (Exception e) {
e.printStackTrace();
}finally{
lock.unlock();
}
}
}
public class Run {
public static void main(String[] args) {
MyService2 myService2 = new MyService2();
ThreadA2 threadA = new ThreadA2(myService2);
threadA.start();
ThreadB2 myThreadB2 = new ThreadB2(myService2);
myThreadB2.start();
}
}
运行结果:
打印 11
复印 22
打印 11
复印 22
打印 11
复印 22
打印 11
复印 22
打印 11
复印 22
打印 11
复印 22
synchronize与ReentrantLock的区别:
1.lock 必须在 finally 块中释放。否则,如果受保护的代码将抛出异常,锁就有可能永远得不到释放。
2 对于synchronized来讲,被synchronized锁定的资源(代码块),线程A,只有执行完毕,才能释放锁,对于长时间的同步块来讲,其他线程线程B在很长时间内都得不到执行,如果B想中断自己,在synchronized锁定下,这种情况B不会中断。ReentranceLock之所以可以重入,是因为线程在执行的过程可以中断,对于某些等待时间较长的同步块,可以中断,而转去执行其他的操作。
3 ReentranceLock可以同时绑定多个Condition,synchronized只能绑定一个Condition,也就是锁定的对象。