java使用wait和notify进行线程的同步,在网上有很多教程了
这里说明一下实现时候需要注意的地方
题目:两个线程,一个线程存数据(name, sex),另一个线程取数据。 交替的打印出存取过程。 - 要求存一条取一条的打印出数据。
package multithread3;
import java.util.*;
public class Demo {
final static Object obj =new Object();//锁
static String name[]=new String[10];
static String sex[]=new String[10];
static int count=0;
static final int SUM=5;
public static void main(String args[]){
Thread thread1=new read();
Thread thread2=new write();
thread1.start();
thread2.start();
}
public static class write extends Thread{
public void run() {
Scanner sc = new Scanner(System.in);
while(count<SUM) {
synchronized (obj) {
if(name[count]!=null) {
try {
obj.wait();
System.out.println("wirte thread wait over");
}catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("write thread get obj lock");
System.out.println("请输入第"+count+"个人的姓名:");
name[count] = sc.nextLine();
System.out.println("请输入性别:");
sex[count] = sc.nextLine();
System.out.println("写好了数据"+count);
obj.notify();
System.out.println("write thread notify read one ");
}
}
sc.close();
}
}
public static class read extends Thread{
public void run() {
while(count<SUM) {
synchronized (obj) {
System.out.println("read thread get obj lock");
try {
if(name[count]==null)
obj.wait();
System.out.println("read thread don't wait");
}catch(InterruptedException e) {
e.printStackTrace();
}
try {
System.out.println("姓名:"+name[count]+",性别:"+sex[count]);
Thread.sleep(50);
System.out.println("读好了数据"+count);
count++;
obj.notify();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("read don't have obj lock");
}
}
}
}
贴上一开始的代码以便对照
package multithread2;
import java.util.*;
public class Bank {
final static Object obj =new Object();//锁
static String name[]=new String[10];
static String sex[]=new String[10];
static int count=0;
static final int SUM=5;
public static void main(String args[]){
Thread thread1=new read();
Thread thread2=new write();
thread1.start();
thread2.start();
}
public static class write extends Thread{
public void run() {
Scanner sc = new Scanner(System.in);
while(count<SUM) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized (obj) {
System.out.println("write thread get obj lock");
System.out.println("请输入第"+count+"个人的姓名:");
name[count] = sc.nextLine();
System.out.println("请输入性别:");
sex[count] = sc.nextLine();
System.out.println("写好了数据"+count);
obj.notify();
System.out.println("write thread notify read one ");
try {
Thread.sleep(800);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("write thread wakeup after 0.8s ");
}
}
sc.close();
}
}
public static class read extends Thread{
public void run() {
while(count<SUM) {
synchronized (obj) {
System.out.println("read thread get obj lock");
try {
if(name[count]==null)
obj.wait();
System.out.println("read thread don't wait");
}catch(InterruptedException e) {
e.printStackTrace();
}
try {
System.out.println("姓名:"+name[count]+",性别:"+sex[count]);
Thread.sleep(50);
System.out.println("读好了数据"+count);
count++;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("read don't have obj lock");
}
}
}
}
一开始我在write线程同步代码块外加了sleep:因为一开始write线程sleep的时候才可以使得read线程获取锁然后进行wait,个人认为wait之后就会让出obj的锁然后使得write线程可以进入syn区执行notify,然而notify之后并没有让出锁,所以必须要等后面等待0.8s后才会使得read线程得到锁,解除wait状态。
所以这样的写法是不对的,正确的写法两个线程进行同步的时候,需要判断什么时候需要读线程,什么时候需要写线程,如果需要读线程了,写现场就必须等待,然后让读线程执行完毕之后notify,同理需要写线程时,读线程也要wait挂起等待。