天天看点

线程间通信及其安全问题

线程间的通行与等待唤醒机制举例:

 一、两个线程:

/**
 * @author flame
 * @createDate 2012-1-3
 * 线程间的通信:
 * 首先,有一个资源,提供存取对象
 * 一个线程往里面注入资源
 * 另一个线程从里面读取资源
 * 多个线程操作同一个个数据,不同的是操作动作不同
 * 唤醒机制:
 * 为避免一个资源注入一般就被另一个资源所读取,所以需要采用唤醒机制。
 * 原理:注入时,注入线程执行状态,读取线程等待状态;注入后,注入线程等待状态,读取线程执行状态。
 * wait()等待
 * notify()唤醒单一线程
 * notifyAll()唤醒所有线程
 * 唤醒只能唤醒同一个锁的等待线程,不能唤醒不同锁的等待线程,也就是说等待线程的锁和唤醒线程的锁必须同一个。
 */
/**
 * 资源,提供姓名和性别
 * @author flame
 * @createDate 2012-1-3
 */
class Result
{
    private String name;
    private String sex;
    private boolean flag = false; 
    public synchronized void set(String name, String sex)
    {
        if(flag)
            try{this.wait();}catch(InterruptedException ex){}
        this.name = name;
        this.sex = sex;
        flag = true;
        this.notify();        
    }
    public synchronized void get()
    {
        if(!flag)
            try{this.wait();}catch(InterruptedException ex){}
        System.out.println(this.name+"...."+this.sex);
        this.flag = false;
        this.notify();
    }
}
/**
 * 注入资源线程
 * @author flame
 * @createDate 2012-1-3
 */
class InputInfo implements Runnable
{
    private Result r;             //声明资源类
    public InputInfo(Result r)    //传入一个资源类,以是得资源为同个资源
    {
        this.r = r;
    }
    public void run()
    {        
        int i= 0,j =0;
        while(i <=500)
        {            
            if(j == 0)
                r.set("flame", "man");                
            else
                r.set("火", "男");                
            j = (j+1)%2;            
            i++;                                
        }        
    }
}
/**
 * 获取资源中的数据
 * @author flame
 * @createDate 2012-1-3
 */
class OutputInfo implements Runnable
{
    private Result r;
    public OutputInfo(Result r)
    {
        this.r = r;
    }
    public void run()
    {
        int i = 0;
        while(i<500)
        {
            r.get();
            i++;                
        }        
    }
}
public class communcationThreadDemo {

    /**
     * 启动线程
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Result r = new Result();
        new Thread(new InputInfo(r)).start();
        new Thread(new OutputInfo(r)).start();
        
    }

}
           

二、多线程 (生产者与消费者)

/**
 * 生产者与消费者举例
 * 当出现多个线程时,唤醒机制的另一种解决方式
 * @author flame
 * @createDate 2012-1-3
 */


/**
 * 资源类
 * 初始化资源对象
 * 控制资源注入和输出线程
 * @author flame
 * @createDate 2012-1-3
 */
class Ruselt
{
    private String name;
    private int count =0;
    private boolean flag = false;
    public synchronized void set(String name)
    {
        while(flag)
            try{
                this.wait();
            }catch(InterruptedException ex)
            {
                System.out.println(ex.getMessage());
            }
        this.name = name +"***----***"+count++;
        System.out.println(Thread.currentThread().getName()+"******生产者******"+this.name);
        this.flag = true;
        this.notifyAll();
    }
    public synchronized void get()
    {
        while(!flag)        //此处如果采用if语句判断,会使得当以线程判断通过而放弃资格后,在苏醒时会不再经过判断而继续执行下面的代码
            try{
                this.wait();
            }catch(InterruptedException ex)
            {
                System.out.println(ex.getMessage());
            }
        System.out.println(Thread.currentThread().getName()+"=====消费者================="+name);
        this.flag = false;
        this.notifyAll();     //唤醒所有线程,避免全部线程处于等待状态
    }
}
class InputComm implements Runnable
{
    private Ruselt r;
    public InputComm(Ruselt r)
    {
        this.r = r;
    }
    public void run()
    {
        int i=0;
        while(i<500)
        {
            r.set("商品");
            i++;
        }
    }
}
class OutputComm implements Runnable
{
    private Ruselt r;
    public OutputComm(Ruselt r)
    {
        this.r = r;
    }
    public void run()
    {
        int i=0;
        while(i<500)
        {
            r.get();
            i++;
        }
    }
}
public class moreThreadDemo {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Ruselt r = new Ruselt();
        new Thread(new InputComm(r)).start();
        new Thread(new OutputComm(r)).start();
    }

}