1. 使用synchronized wait(), notify()实现
public class TwoThreadProcess {
public static void main(String[] args) {
Outputer outputer = new Outputer();
new Thread(new Runnable() {
@Override
public void run() {
try {
while(true) {
outputer.output(Thread.currentThread().getName(), "ZhangSan");
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
try {
while(true) {
outputer.output(Thread.currentThread().getName(), "WangWu");
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
static class Outputer {
private String lastThreadName = Thread.currentThread().getName();
public synchronized void output(String threadName, String name) {
try {
Thread.sleep(1000);
//两次线程的名字一致,是同一线程,则线程释放同步锁,等待其他线程执行后将其唤醒
while (lastThreadName.equals(threadName)) {
this.wait(); //当前线程进入等待状态,并且释放同步锁
}
System.out.print(Thread.currentThread().getName() + ": ");
int len = name.length();
for (int i = 0; i < len; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
lastThreadName = threadName;
//线程执行结束后,当前线程随机唤醒一个处于等待的线程
this.notify();
}
}
}
}
通过(线程名)判断,让执行过的线程进入Waiting状态,待未执行的线程执行后,唤醒处于等待状态的线程。
notify(): (随机)唤醒一个等待状态的线程
notifyAll(): 唤醒所有处于等待状态的线程
2. 使用Lock Condition await(), signal()实现
public class TwoThreadProcess {
public static void main(String[] args) {
MyBusiness myBusiness = new MyBusiness();
new Thread(new Runnable() {
@Override
public void run() {
try {
while(true) {
myBusiness.output("ZhangSan");
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
try {
while(true) {
myBusiness.output("WangWu");
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class MyBusiness{
private Lock reentrantLock = new ReentrantLock();
private Condition condition = reentrantLock.newCondition();
private String lastThreadName = "";
public void output(String name) {
String threadName = Thread.currentThread().getName();
try {
reentrantLock.lock();
//两次线程的名字一致,是同一线程,则线程释放同步锁,等待其他线程执行后将其唤醒
while (lastThreadName.equals(threadName)) {
//当前线程进入等待状态,并且释放同步锁
condition.await();
}
System.out.print(Thread.currentThread().getName() + ": ");
int len = name.length();
for (int i = 0; i < len; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
lastThreadName = threadName;
//线程执行结束后,唤醒一个处于等待的线程
condition.signal();
reentrantLock.unlock();
}
}
}
- Condition是个接口,基本的方法就是await()和signal()方法;
- Condition依赖于Lock接口,生成一个Condition的基本代码是lock.newCondition()
- 调用Condition的await()和signal()方法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以使用
Conditon中的await()对应Object的wait()
Condition中的signal()对应Object的notify()
Condition中的signalAll()对应Object的notifyAll()
Condition相比较于wait()和notify()的真正优势
多少个线程交替执行就需要创建多少个Condition,
Condition的await()、signal()这种方式实现线程间协作更加安全和高效
public class ThreeThreadProcess {
public static void main(String[] args) {
MyBusiness3 myBusiness3 = new MyBusiness3();
Lock reentrantLock = new ReentrantLock();
Condition condition1 = reentrantLock.newCondition();
Condition condition2 = reentrantLock.newCondition();
Condition condition3 = reentrantLock.newCondition();
new Thread(new Runnable() {
@Override
public void run() {
while(true) {
myBusiness3.output(reentrantLock,condition1, condition2, "1111");
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while(true) {
myBusiness3.output(reentrantLock, condition2, condition3, "2222");
}
}
}).start();
while(true) {
myBusiness3.output(reentrantLock, condition3, condition1,"3333");
}
}
}
class MyBusiness3{
private String lastThreadName = "";
public void output(Lock reentrantLock, Condition curr, Condition next, String name) {
String threadName = Thread.currentThread().getName();
try {
reentrantLock.lock();
Thread.sleep(1000);
//如果和上一线程的名字一致,则线程释放同步锁,等待其他线程执行后将其唤醒
while (lastThreadName.equals(threadName)) {
//当前线程进入等待状态,并且释放同步锁
curr.await();
}
System.out.print(Thread.currentThread().getName() + ": ");
int len = name.length();
for (int i = 0; i < len; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
lastThreadName = threadName;
//线程执行结束后,唤醒一个处于等待的线程
next.signal();
reentrantLock.unlock();
}
}
}