什么是多线程之间通讯?
多线程之间通讯,其实就是多个线程在操作同一个资源,但是操作的动作不同。
现在假设有这么一个需求:第一个线程写入(input)用户,另一个线程取读取(out)用户.实现读一个,写一个操作。
代码:
package com.Thread.test;
public class Res {
public String name;
public String sex;
}
class InThread extends Thread {
Res res;
public InThread(Res r) {
this.res = r;
}
@Override
public void run() {
int i = 0;
while (true) {
if (i == 0) {
res.name = "吕布";
res.sex = "男";
} else {
res.name = "貂蝉";
res.sex = "女";
}
i = (i + 1) % 2;
}
}
}
class OutThread extends Thread {
Res res;
public OutThread(Res r) {
this.res = r;
}
@Override
public void run() {
while (true) {
System.out.println(res.name + "--" + res.sex);
}
}
}
class Main {
public static void main(String[] args) {
//同一个资源
Res res = new Res();
//生产者线程
new InThread(res).start();
//消费者线程
new OutThread(res).start();
}
}
结果:
数据发生错乱,造成线程安全问题
解决方法加锁,注意这个锁对于两个线程来说必须是同一把锁
res是共享资源,所以这里使用res作为锁最合适
package com.Thread.test;
public class Res {
public String name;
public String sex;
}
class InThread extends Thread {
Res res;
public InThread(Res r) {
this.res = r;
}
@Override
public void run() {
int i = 0;
while (true) {
synchronized (res){
if (i == 0) {
res.name = "吕布";
res.sex = "男";
} else {
res.name = "貂蝉";
res.sex = "女";
}
i = (i + 1) % 2;
}
}
}
}
class OutThread extends Thread {
Res res;
public OutThread(Res r) {
this.res = r;
}
@Override
public void run() {
while (true) {
synchronized (res){
System.out.println(res.name + "--" + res.sex);
}
}
}
}
class Main {
public static void main(String[] args) {
//同一个资源
Res res = new Res();
//生产者线程
new InThread(res).start();
//消费者线程
new OutThread(res).start();
}
}
加锁后:
wait()、notify、notifyAll()方法
wait()、notify()、notifyAll()是三个定义在Object类里的方法,可以用来控制线程的状态。这三个方法最终调用的都是jvm级的native方法。随着jvm运行平台的不同可能有些许差异。
wait方法:使持有该对象的线程把该对象的控制权交出去,然后处于等待状态。
notify方法:通知某个正在等待这个对象的控制权的线程可以继续运行。
notifyAll方法:通知所有等待这个对象控制权的线程继续运行。
注意注意注意:一定要在线程同步中使用,并且是同一个锁的资源
package com.Thread.test;
public class Res {
public String name;
public String sex;
//线程通讯标识, true表示生产者等待消费者消费后再创建,false表示消费者等待生产者生产后再消费
public boolean flag = false;
}
class InThread extends Thread {
Res res;
public InThread(Res r) {
this.res = r;
}
@Override
public void run() {
int i = 0;
while (true) {
synchronized (res){
if(res.flag){
try {
res.wait();//一直等待直到被唤醒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (i == 0) {
res.name = "吕布";
res.sex = "男";
} else {
res.name = "貂蝉";
res.sex = "女";
}
i = (i + 1) % 2;
res.flag = true;
res.notify();//唤醒正在等待这个对象的控制权的线程可以继续运行
}
}
}
}
class OutThread extends Thread {
Res res;
public OutThread(Res r) {
this.res = r;
}
@Override
public void run() {
while (true) {
synchronized (res){
if(!res.flag){
try {
res.wait();//一直等待直到被唤醒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(res.name + "--" + res.sex);
res.flag = false;
res.notify();//唤醒正在等待这个对象的控制权的线程可以继续运行
}
}
}
}
class Main {
public static void main(String[] args) {
//同一个资源
Res res = new Res();
//生产者线程
new InThread(res).start();
//消费者线程
new OutThread(res).start();
}
}
结果:
wait与sleep区别?
对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。
wait 用于同步中,可以释放锁的资源,需要nofity才能从休眠状态变为运行状态。
sleep 不会释放锁的资源,时间到期,就从休眠状态变为运行状态。
他们的相同点都是做休眠。