Java线程间通信的同步问题、wait/notify使用

Java线程间通信简单来说就是多个线程同时操作同一个资源,比如一个线程设置了姓名、性别,另一个线程读取姓名、性别。

伴随而来的就是同步问题:比如线程a先设置了张三、男,后设置了李四、女,线程b要打印这些信息,由于多线程的随机性,a设置张三、男后,然后a又设置了李四,还未设置性别时,b这时候读取数据,独到的就是李四、男,这样结果就不对了。解决方法就是加锁,保证a在赋值时,b没有读取;b读取时,a没有在赋值。

wait:java.lang.Object.wait(),java api是这么解释的:当前线程必须拥有此对象监视器。该线程发布对此监视器的所有权并等待,

直到其他线程通过调用notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。然后该线程将等到重新

获得对监视器的所有权后才能继续执行。

notify:唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。

选择是任意性的,并在对实现做出决定时发生。线程通过调用其中一个wait 方法,在对象的监视器上等待。

很难懂吧,简单来说就是让持有当前锁对象的线程等待或启动。

wait 和 notify 都是用在同步中,因为要对持有监视器(锁)的线程操作,所以要是用在同步中,只有同步才具有锁。
为什么操作线程的方法要定义在Object类中?
因为这些方法在操作同步线程时,都必须要表示他们所操作线程持有的锁。只有同一个锁上的被等待线程可以被同一个锁上的notify唤醒,不可以对不同锁中的线程进行唤醒。
等待和唤醒必须是同一个锁。而锁可以是任意对象,所以可以被任意对象调用的方法定义在Object类中。


package threaddemo.deadthread;



import java.io.ObjectInputStream.GetField;


import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;


/**
 * 多线程通信
 * 
 * @author JYF
 * 
 */
public class ThreadCommunicateClient {
public static void main(String[] args) {
PropertyConfigurator.configure("src/log4j.properties");
User user = new User();
Generator generator = new Generator(user);
Consumer consumer = new Consumer(user);
Thread createThread = new Thread(generator, "generator.thread");
Thread consumerTherad = new Thread(consumer, "consumer.thread");
createThread.start();
consumerTherad.start();
}
}


class User {
private String name;
private String sex;
private boolean isWriten = false;


public String getSex() {
return sex;
}


public void setSex(String sex) {
this.sex = sex;
}


public String getName() {
return name;
}


public void setName(String name) {
this.name = name;
}


public boolean isWriten() {
return isWriten;
}


public void setWriten(boolean isWriten) {
this.isWriten = isWriten;
}


}


/**
 * \ 生成用户信息
 * 
 * @author JYF
 * 
 */
class Generator implements Runnable {
User user;
Logger log = Logger.getLogger(getClass());


Generator(User user) {
this.user = user;
}


@Override
public void run() {
int i = 0;
while (true) {
synchronized (user) {


if (!user.isWriten()) {
if (i % 2 == 0) {


user.setName("张三");
user.setSex("男");
user.setWriten(true);
} else {
user.setName("李四");
user.setSex("女");
user.setWriten(true);
}
i = i + 1;
user.notify();
}
else {
try {
user.wait();
} catch (InterruptedException e) {
log.error("");
}
}
}
}
}
}


/**
 * 消费用户信息
 * 
 * @author JYF
 * 
 */
class Consumer implements Runnable {
User user;
Logger log = Logger.getLogger(getClass());


Consumer(User user) {
this.user = user;
}


@Override
public void run() {
while (true) {
synchronized (user) {
if (user.isWriten()) {
log.info(user.getName() + "  " + user.getSex());
user.setWriten(false);
user.notify();
}
else {
try {
user.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}
}
}

}


参考:java api,毕向东老师多线程相关视频

猜你喜欢

转载自blog.csdn.net/a1257427517/article/details/78760232