您的位置:首页 > 大数据 > 人工智能

【并发】3、LockSupport阻塞与唤醒,相较与wait和notify

2018-03-04 13:52 465 查看
我们可以使用wait和notify分别对象线程进行阻塞或者唤醒,但是我们也可以使用LockSupport实现一样的功能,并且在实际使用的时候,个人感觉LockSupport会更加顺手

范例1,wait与notify

class WaitTest1 {

static class ThreadA extends Thread {
public ThreadA(String name) {
super(name);
}

@Override
public void run() {
synchronized (this) {
System.out.println(Thread.currentThread().getName() + " wakup others");
this.notify(); // 唤醒当前线程对象
for (int i = 0; i < 10; ++i) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("唤醒当前线程对象之后" + i);
}
}

for (int i = 0; i < 10; ++i) {
System.out.println("唤醒当前线程对象,释放锁之后前" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("唤醒当前线程对象,释放锁之后" + i);
}

}
}

public void mian1() {
ThreadA ta = new ThreadA("ta");

//因为wait需释放锁,所以必须在synchronized中使用(没有锁定则么可以释放?没有锁时使用会抛出IllegalMonitorStateException(正在等待的对象没有锁))
synchronized (ta) {
try {

System.out.println(Thread.currentThread().getName() + " start ta");
ta.start();

System.out.println(Thread.currentThread().getName() + " block");
// 主线程等待,释放当前线程锁
ta.wait();

System.out.println(Thread.currentThread().getName() + " continue");

} catch (Exception e) {
e.printStackTrace();
}
}
}
}




运行结果:



范例2,locksupport

class LockSupportTest1 {
private static Thread mainThread;

static class ThreadA extends Thread {
public ThreadA(String name) {
super(name);
}

@Override
public void run() {
synchronized (this) {
System.out.println(Thread.currentThread().getName() + " wakup others");
//                this.notify(); // 唤醒当前线程对象
LockSupport.unpark(mainThread);  //this,这里就不能使用this了,如果这里使用this,那么其实并没有释放这个对象的锁,释放的对象是ta的锁,那就会造成死锁
for (int i = 0; i < 10; ++i) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("唤醒当前线程对象之后" + i);
}
}

for (int i = 0; i < 10; ++i) {
System.out.println("唤醒当前线程对象,释放锁之后前" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("唤醒当前线程对象,释放锁之后" + i);
}

}
}

public void main1() {
ThreadA ta = new ThreadA("LockSupportTest1");
//获取当前主线程对象
mainThread = Thread.currentThread();

System.out.println(Thread.currentThread().getName() + " start ta");
ta.start();

System.out.println(Thread.currentThread().getName()+" block");

//对主线程进行阻塞
LockSupport.park(mainThread);

System.out.println(Thread.currentThread().getName()+" continue");

}

}




效果展示:



两者相比我们就会发现,

1、locksupport不需要先进入对应的同步锁,也就是synchronize获取当前锁,然后才能使用wait进行释放

2、locksupport不局限在本线程中,更感觉是跳脱在线程外,对线程进行操控,不想synchronize中的notify,在没有退出同步代码块之前,这个锁实际上还是当前线程占用的,不管是否执行了notify

  只有在退出了同步代码块,这个锁才会真正的被释放
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: