您的位置:首页 > 编程语言 > Java开发

JAVA学习第二十六课(多线程(五))- 多线程间的通信问题

2017-08-02 11:00 344 查看


一、线程间的通信

实例代码:

[b]需求是:输入一个姓名和性别后,就输出一个姓名和性别

[/b]

class Resource
{
String name;
String sex ;
}
class Input implements Runnable
{
Resource r;
Input(Resource r)
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
synchronized (r)
{
if(x==0)
{
r.name = "BLF";
r.sex = "male";
}
else {
r.name = "妮妮妮妮";
r.sex = "female";
}
x = (++x)%2;
}
}
}
}

class Output implements Runnable
{
Resource r;
public Output(Resource r) {
// TODO Auto-generated constructor stub
this.r = r;
}
public void run()
{
while(true)
{
synchronized (r) //输入和输出都是应用同一个锁
{
System.out.println(r.name+"..."+r.sex);
}
}
}
}
public class Main
{
public static void main(String[] args)
{
Resource r = new Resource();//共享同一资源
Input in = new Input(r);
Output out = new Output(r);
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
}
}


上述代码尽管攻克了。多线程处理同一资源问题,可是出现了一个问题就是,打印非常多一个人名和性别后再打印还有一个,无法实现交替输出。原因:输入线程获取运行权后,不会运行一次,输入姓名和性别,输入线程还拥有运行权。一直赋值。等到切换到输出运行权后,输出最后输入的姓名和性别。可是输出线程也不会仅仅输出一次,一直输出,所以出现打印非常多同一姓名和性别的问题

二、线程的等待/唤醒机制:

用一个boolean值推断是否有数据,有就不放。没有就放

输入线程运行时推断是否有数据,有。就释放运行权,再释放运行资格,进入冻结状态。输出线程运行。输出后boolean值置为false

Input:
if(flag)//有值
wait();//当前冻结,切换输出线程
flag = true;
notify();

Output:
if(!flag)
wait();
flag = false;//flag置为假。输出完成
notify();//唤醒输入线程


等待/唤醒机制:

方法:

1.wait();//使线程进入冻结状态,CPU释放运行权和运行资格,被wait()的线程会被存储到线程池中
2.notify();//唤醒线程池中的随意的一个线程
3.notifyAll();//唤醒全部线程,使之处于运行状态或暂时堵塞状态,总之,使其具备运行资格


这些方法必须定义在同步中。这些方法是用于操作线程状态的方法,所以必须明白在哪个锁上的线程

(wait()A锁的线程。仅仅能用A锁的notify唤醒A锁的线程。



了解:而wait()等方法是定义在Object类中的。这些方法是监视器的方法。而监视器呢。就能够理解为锁,控制哪个锁所属下的线程,而锁又能够是随意的,而全部的类都是继承于Object类的,所以wait()等类是定义在Object里

下述代码就攻克了上述代码的问题,实现了输入输出线程的交替运行

class Resource extends Object
{
String name;
String sex ;
boolean flag = false;
}
class Input implements Runnable
{
Resource r;
Input(Resource r)
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
synchronized (r)
{
if(r.flag)
{
try {
r.wait();
} catch (Exception e) {
// TODO: handle exception
}

}

if(x==0)
{
r.name = "BLF";
r.sex = "male";
}
else {
r.name = "妮妮妮妮";
r.sex = "female";
}
r.flag = true;
r.notify();
x = (++x)%2;
}
}
}
}

class Output implements Runnable
{
Resource r;
public Output(Resource r) {
// TODO Auto-generated constructor stub
this.r = r;
}
public void run()
{

while(true)
{
synchronized (r)
{
if(!r.flag)
{
try {
r.wait();
} catch (Exception e) {
// TODO: handle exception
}
}

System.out.println(r.name+"..."+r.sex);
r.flag = false;
r.notify();
}
}
}
}
public class Main
{
public static void main(String[] args)
{

Resource r = new Resource();
Input in = new Input(r);
Output out = new Output(r);
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
}
}


三:等待唤醒机制代码优化

资源中的成员为了可控,应该为私有的。对外提供方法

所以同步的操作。就在Resource类中运行,应用同步函数

class Resource extends Object
{
private String name;
private String sex ;
private boolean flag = false;
public synchronized void set(String name,String sex)
{
// TODO Auto-generated constructor stub
if(flag)
{
try {
this.wait();
} catch (Exception e) {
// TODO: handle exception

}
}

this.name = name;
this.sex = sex;

flag = true;
this.notify();
}
public synchronized void out()
{
if(!flag)
{
try {
this.wait();
} catch (Exception e) {
// TODO: handle exception
}
System.out.println(name+"  :  "+sex);
flag = false;
this.notify();
}
}
}
class Input implements Runnable
{
Resource r;
Input(Resource r)
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
if(x==0)
{
r.set("BLF", "male");
}
else
{
r.set("妮妮妮妮", "female");
}
x = (++x)%2;

}
}
}
class Output implements Runnable
{
Resource r;
public Output(Resource r) {
// TODO Auto-generated constructor stub
this.r = r;
}
public void run()
{
while(true)
{
r.out();
}
}
}
public class Main
{
public static void main(String[] args)
{

Resource r = new Resource();
Input in = new Input(r);
Output out = new Output(r);
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐