什么是多线程之间通讯?
多线程之间通讯,其实就是多个线程在操作同一个资源,但是操作的动作不同。
画图演示
方法一:synchronized和wait配套使用
Object类的方法部分截图:
其中我们要用到的是wait()、notify()、notifyAll()是三个方法,可以用来控制线程的状态。
这三个方法最终调用的都是jvm级的native方法。随着jvm运行平台的不同可能有些许差异。
- 如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态。
- 如果对象调用了notify方法就会通知某个正在等待这个对象的控制权的线程可以继续运行。
- 如果对象调用了notifyAll方法就会通知所有等待这个对象控制权的线程继续运行。
实现:
问题描述:第一个线程写入(input)用户,另一个线程取读取(out)用户.实现读一个,写一个操作。
/**
* 共享资源
* @author lenovo
*
*/
class Res{
public String name;
public String sex;
public Boolean flag = false;
}
/**
* 写入线程
* @author lenovo
*
*/
class InputThread extends Thread{
public Res res;
public InputThread(Res res) {
this.res = res;
}
@Override
public void run() {
int count = 0;
while(true) {
synchronized (res) {
if(res.flag) {
try {
//wait要和synchronized 配套使用
//wait可以释放锁,而sleep不能释放锁
res.wait();
} catch (Exception e) {
// TODO: handle exception
}
}
if(count == 0) {
res.name = "阿斗";
res.sex = "男";
}else {
res.name = "老嫂子";
res.sex = "女";
}
count = (count+1)%2;
res.flag = true;
//notify和wait一起使用,
//唤醒另一个线程,让另一个线程从阻塞状态变为运行状态
res.notify();
}
}
}
}
/**
* 读取线程
* @author lenovo
*
*/
class OutputThread extends Thread{
public Res res;
public OutputThread(Res res) {
this.res = res;
}
@Override
public void run() {
while(true) {
synchronized (res) {
if(!res.flag) {
try {
res.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(res.name + "----" +res.sex);
res.flag = false;
res.notify();
}
}
}
}
/**
*
* @author lenovo
*
*/
public class ThreadDemo01 {
public static void main(String[] args) {
Res res = new Res();
InputThread inputThread = new InputThread(res);
OutputThread outputThread = new OutputThread(res);
inputThread.start();
outputThread.start();
}
}
方法二:Lock接口与Condition对象实现
①Lock接口的实现类ReentrantLock作用:
ReentrantLock是一个可重入的互斥锁,ReentrantLock由最近成功获取锁,还没有释放的线程所拥有,当锁被另一个线程拥有时,调用lock的线程可以成功获取锁。如果锁已经被当前线程拥有,当前线程会立即返回
②Contion接口
③Condition接口的方法:
Condition condition = lock.newCondition();
await(); 类似wait
signal() 类似notify
signalAll 类似notifyAll
实现:
/**
* 共享资源
* @author lenovo
*
*/
class Res{
public String name;
public String sex;
public Boolean flag = false;
public Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
}
/**
* 写入线程
* @author lenovo
*
*/
class InputThread extends Thread{
public Res res;
public InputThread(Res res) {
this.res = res;
}
@Override
public void run() {
int count = 0;
while(true) {
try {
res.lock.lock();
if(res.flag) {
res.condition.await();
}
if(count == 0) {
res.name = "阿斗";
res.sex = "男";
}else {
res.name = "老嫂子";
res.sex = "女";
}
count = (count+1)%2;
res.flag = true;
res.condition.signal();
} catch (Exception e) {
// TODO: handle exception
}finally {
res.lock.unlock();
}
}
}
}
/**
* 读取线程
* @author lenovo
*
*/
class OutputThread extends Thread{
public Res res;
public OutputThread(Res res) {
this.res = res;
}
@Override
public void run() {
while(true) {
try {
res.lock.lock();
if(!res.flag) {
res.condition.await();
}
System.out.println(res.name + "----" +res.sex);
res.flag = false;
res.condition.signal();
} catch (Exception e) {
// TODO: handle exception
}finally {
res.lock.unlock();
}
}
}
}
/**
*
* @author lenovo
*
*/
public class ThreadDemo01 {
public static void main(String[] args) {
Res res = new Res();
InputThread inputThread = new InputThread(res);
OutputThread outputThread = new OutputThread(res);
inputThread.start();
outputThread.start();
}
}