您的位置:首页 > 其它

线程通信

2016-06-05 14:42 106 查看
讲解等待唤醒机制之前,有必要搞清一个概念――线程之间的通信:多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同。通过一定的手段使各个线程能有效的利用资源。而这种手段即―― 等待唤醒机制。
等待唤醒机制所涉及到的方法:
wait() :等待,将正在执行的线程释放其执行资格 和 执行权,并存储到线程池中。
notify():唤醒,唤醒线程池中被wait()的线程,一次唤醒一个,而且是任意的。
notifyAll(): 唤醒全部:可以将线程池中的所有wait() 线程都唤醒。
public class NumberHolder
{    private int number;    public synchronized void increase()
{        if (0 != number)
{            try
{
wait();
}            catch (InterruptedException e)
{
e.printStackTrace();
}
}        // 能执行到这里说明已经被唤醒        // 并且number为0
number++;
System.out.println(number);        // 通知在等待的线程        notify();
}    public synchronized void decrease()
{        if (0 == number)
{            try
{
wait();
}            catch (InterruptedException e)
{
e.printStackTrace();
}

}        // 能执行到这里说明已经被唤醒        // 并且number不为0
number--;
System.out.println(number);
notify();
}

}public class IncreaseThread extends Thread
{    private NumberHolder numberHolder;    public IncreaseThread(NumberHolder numberHolder)
{        this.numberHolder = numberHolder;
}

@Override    public void run()
{        for (int i = 0; i < 20; ++i)
{            // 进行一定的延时
try
{
Thread.sleep((long) Math.random() * 1000);
}            catch (InterruptedException e)
{
e.printStackTrace();
}            // 进行增加操作            numberHolder.increase();
}
}

}public class DecreaseThread extends Thread
{    private NumberHolder numberHolder;    public DecreaseThread(NumberHolder numberHolder)
{        this.numberHolder = numberHolder;
}

@Override    public void run()
{        for (int i = 0; i < 20; ++i)
{            // 进行一定的延时
try
{
Thread.sleep((long) Math.random() * 1000);
}            catch (InterruptedException e)
{
e.printStackTrace();
}            // 进行减少操作            numberHolder.decrease();
}
}

}public class NumberTest
{    public static void main(String[] args)
{
NumberHolder numberHolder = new NumberHolder();

Thread t1 = new IncreaseThread(numberHolder);
Thread t2 = new DecreaseThread(numberHolder);

t1.start();
t2.start();
}

}
因为就是两个线程所以就是可以互相切换,即必须是互相切换,但是如果是四个线程呢?会怎么样呢?那么再来两个线程; 即把其中的NumberTest类改为如下:
public class NumberTest
{    public static void main(String[] args)
{
NumberHolder numberHolder = new NumberHolder();

Thread t1 = new IncreaseThread(numberHolder);
Thread t2 = new DecreaseThread(numberHolder);

Thread t3 = new IncreaseThread(numberHolder);
Thread t4 = new DecreaseThread(numberHolder);

t1.start();
t2.start();

t3.start();
t4.start();
}

}
为什么两个线程的时候执行结果正确而四个线程的时候就不对了呢?  因为线程在wait()的时候,接收到其他线程的通知,即往下执行,不再进行判断。两个线程的情况下,唤醒的肯定是另一个线程;但是在多个线程的情况下,执行结果就会混乱无序。比如,一个可能的情况是,一个增加线程执行的时候,其他三个线程都在wait,这时候第一个线程调用了notify()方法,其他线程都将被唤醒,然后执行各自的增加或减少方法。  解决的方法就是:在被唤醒之后仍然进行条件判断,去检查要改的数字是否满足条件,如果不满足条件就继续睡眠。把两个方法中的if改为while即可。
public class NumberHolder
{    private int number;    public synchronized void increase()
{        while (0 != number)
{            try
{
wait();
}            catch (InterruptedException e)
{
e.printStackTrace();
}
}        // 能执行到这里说明已经被唤醒        // 并且number为0
number++;
System.out.println(number);        // 通知在等待的线程        notify();
}    public synchronized void decrease()
{        while (0 == number)
{            try
{
wait();
}            catch (InterruptedException e)
{
e.printStackTrace();
}

}        // 能执行到这里说明已经被唤醒        // 并且number不为0
number--;
System.out.println(number);
notify();
}

}
这样就可以解决了线程的混乱的问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: