1.线程间通讯的理解
线程间通讯:
其实就是多个线程在操作同一个资源,但是操作的动作不同
2.线程间通信的示例代码
描述:存在两个线程,一个线程负责写入信息,另一个线程负责打印信息。
model类Student 属性name sex (私有类)
线程:Input类,Output类。
model类Student 属性name sex (私有类)
线程:Input类,Output类。
启动两个线程分别执行打印和写入操作。
/**
*
*/
package threadCommnication;
/**
* <p>Title: InputOutputDemo</p>
* <p>Description: </p>
* <p>Company: </p>
* @author 夏 杰
* @date 2015年12月12日 下午8:40:53
* @vesion 1.0
*/
public class InputOutputDemo {
public static void main(String[] args) {
Student student = new Student();
Input input = new Input(student);
Output output = new Output(student);
//存入学生信息的线程
new Thread(input).start();
//打印学生信息的线程
new Thread(output).start();
}
}
/**
*
*/
package threadCommnication;
public class Input implements Runnable{
private Student student;
boolean flag = false;
//保证传入对象唯一性
public Input(Student student) {
this.student = student;
}
@Override
public void run() {
/*在这里定义两个学生切换着存入学生的信息
*/
while(true){
if(flag){
student.name = "xy";
student.sex = "woman";
flag = false;
}else{
student.name = "乔布斯";
student.sex = "男男男男男男";
flag = true;
}
}
}
}
/**
*
*/
package threadCommnication;
public class Output implements Runnable{
private Student stu;
public Output(Student stu){ //保证传入对象唯一性
this.stu = stu;
}
@Override
public void run() {
while(true){
System.out.println(stu.name+"..."+stu.sex);
}
}
}
public class Student {
String name;
String sex;
}
当线程执行之后,会出现线程间数据问题。(这里需要使用同步的方法来修改代码)
注意:最好不要在整个方法上加锁,最好在代码块上,因为一个方法上不可能全部都是互斥的,这样执行效率会比较低
这里开始尝试给线程加锁
但是虽然加了同步锁,但是由于加的锁并不是同一个把锁,所以不能够限制对象同步,还会出现不同步的情况
这是就需要检查同步的前提条件了:
同步的前提:
1、至少有两个线程,在程序中运行
2、同步时使用同一个锁对象
1、至少有两个线程,在程序中运行
2、同步时使用同一个锁对象
注意:最好不要在整个方法上加锁,最好在代码块上,因为一个方法上不可能全部都是互斥的,这样执行效率会比较低
改成这样就行了,同用student这把锁
3.多线程中的唤醒等待机制(重要)
java Object类中存在以下方法:
wait():
notify();
notifyAll();
特点:都使用在同步当中,因为要对持有锁(监视器)的对象操作。
所以要在同步中使用,因为同步中才有锁。
描述:要求input类读入一个信息,紧接着output就打印出这条信息。
解决思路:
我们需要将这个类添加一个标识flag。
flag==flase时:表示input没有信息
input开始读入信息,将flag设置为true,并将output唤醒
flag==true时:表示input有信息。
ouput开始打印信息,将flag设置为false,并唤醒input
- public class InputOutputDemo1{
- public static void main(String args[]){
- Student stu = new Student();
- Input in = new Input(stu);
- Output out = new Output(stu);
- Thread t1 = new Thread(in); //存入学生信息的线程
- Thread t2 = new Thread(out); //打印学生信息的线程
- t1.start();
- t2.start();
- }
- }
- class Input implements Runnable{
- private Student stu;
- boolean flag = false;
- int x=0;
- public Input(Student stu){
- this.stu = stu;
- }
- public void run(){//这个线程的run方法负责将姓名和性别存入
- /*在这里定义两个学生切换着存入学生的信息
- */
- while(true){
- if(flag){
- stu.set("xy","woman");
- flag = false;
- }else{
- stu.set("李志磊","男男男男男");
- flag = true;
- }
- }
- }
- }
- class Output implements Runnable{
- private Student stu;
- public Output(Student stu){ //保证传入对象唯一性
- this.stu = stu;
- }
- public void run(){
- while(true){
- stu.out();
- }
- }
- }
- class Student{
- private String name;
- private String sex;
- private boolean flag; //设置标志,默认为false
- public synchronized void set(String name,String sex){
- if(flag)
- try{this.wait();}catch(Exception e){};
- this.name = name;
- this.sex = sex;
- flag = true;
- this.notify();
- }
- public synchronized void out(){
- if(!flag){
- try{this.wait();}catch(Exception e){};
- }else{
- System.out.println(name+"-----"+sex);
- flag = false;
- this.notify();
- }
- }
- }