您的位置:首页 > 职场人生

黑马程序员-Java基础-多线程间通讯

2013-11-22 18:56 357 查看
---------------------
ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------

* 线程间通讯:
* 其实就是多线程在操作同一个资源,但是操作的动作不同。

* wait:
* notify:
* notifyAll:
*都使用在同步中,因为要对持有监视器的线程操作,只有同步才有锁。

       * Lock是从1.5之后的新特性,

       * 提供了显式的锁机制,以及显示的锁对象 上的等待唤醒操作机制。

        * 一个锁可以对应多个condition对象,以前锁只能对应一个对象,容易产生死锁。

 

       * 将同步中的synchronized替换成了实现Lock操作。

       *  condition对象中有await(),signal,signalAll方法

       *  将Object中的wait,notify,notifyAll替换。

       * 该对象可以Lock锁进行获取。

* stop方法已经过时。
* 停止线程的原理:
* 停止线程,只要停止run结束。
* 开启多线程运行,运行代码通常是循环结构。
* 只要控制循环,就可以让run方法结束。也就是线程结束。

* 特殊情况:
* 当线程处于冻结状态,就不会读取到标记,那么线程就不会结束。
* 当没有指定的方式让冻结的线程恢复到运行状态时,这时需要对冻结进行清除。
* 强制让线程恢复到运行状态中来,这样可以操作标记让线程结束。
*
* Thread类提供了方法interrupt(),清除线程的冻结状态,然后利用标记flag结束线程。。

*为什么这些操作线程的方法要定义在Object类中呢?
*因为这些方法在操作同步中线程时,都必须要标识它们所操作线程中的锁。
*只有同一个锁上的被等待线程,可以被锁上notify唤醒。不可以对不同锁中的线程进行唤醒。
*也就是说,等待和唤醒必须是同一个锁。而锁可以是任意对象,所以可以被任意对象的方法定义在Object类中。

        
          下面一生产者和消费者的例子说明线程间通讯。
         方式一:使用Synchronized方式实现:代码如下:
         
package com.itheima.day12;
/**
* 生产者-消费者举例
* notifyAll适合于多个生产者和多个消费者的情况。实际中较为通用的方式。
* 对于多个生产者和消费者,为什么要定义while判断标记呢?
* 原因:让被唤醒的线程再一次判断标记。
* 为什么定义notifyAll
* 因为需呀唤醒对方线程,如果只用notify,容易出现只唤醒本方线程的情况,导致程序中的所有线程都等待。
*/
public class ProducerConsumerDemo {

public static void main(String[] args)
{

Resource r = new Resource();
Producer pro = new Producer(r);
Consumer con = new Consumer(r);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(pro);
Thread t3 = new Thread(con);
Thread t4 = new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}

}
class Resource
{
private String  name;
private int count = 1;
private boolean flag = false;
public synchronized void set(String name)
{
while(flag)
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
this.name = name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"-生产者------"+this.name);
flag = true;
this.notifyAll();
}
public synchronized void out()
{
while(!flag)
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"-消费者-"+this.name);
flag = false;
this.notifyAll();
}
}
class Producer implements Runnable
{
private Resource re;
Producer(Resource re)
{
this.re = re;
}
public void run()
{
while(true)
{
re.set("+商品+");
}
}
}
class Consumer implements Runnable
{
private Resource re;
Consumer(Resource re)
{
this.re = re;
}
public void run()
{
while(true)
{
re.out();
}
}

}
/*适合于消费者一个,生产者也是一个的情况
public class ProducerConsumerDemo {

public static void main(String[] args)
{

Resource r = new Resource();
Producer pro = new Producer(r);
Consumer con = new Consumer(r);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(con);
t1.start();
t2.start();

}

}
class Resource
{
private String  name;
private int count = 1;
private boolean flag = false;
public synchronized void set(String name)
{
if(flag)
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
this.name = name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"-生产者------"+this.name);
flag = true;
notify();
}
public synchronized void out()
{
if(!flag)
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"-消费者-"+this.name);
flag = false;
notify();
}
class Producer implements Runnable
{
private Resource re;
Producer(Resource re)
{
this.re = re;
}
public void run()
{
while(true)
{
re.set("+商品+");
}
}
}
class Consumer implements Runnable
{
private Resource re;
Consumer(Resource re)
{
this.re = re;
}
public void run()
{
while(true)
{
re.out();
}
}
}
*/
实现方式二:Lock锁实现线程间通讯
package com.itheima.day12;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
* 生产者-消费者举例
*
* Lock是从1.5之后的新特性,
* 提供了显式的锁机制,以及显示的锁对象 上的等待唤醒操作机制。
* 一个锁可以对应多个condition对象,以前锁只能对应一个对象,容易产生死锁。
*
* 将同步中的synchronized替换成了实现Lock操作。
*  condition对象中有await(),signal,signalAll方法
*  将Object中的wait,notify,notifyAll替换。
* 该对象可以Lock锁进行获取。
* 在该示例中,实现了本方只唤醒对方的操作。
*
*/
public class LockProducerConsumerDemo {

public static void main(String[] args)
{

Resource1 r = new Resource1();
Producer1 pro = new Producer1(r);
Consumer1 con = new Consumer1(r);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(pro);
Thread t3 = new Thread(con);
Thread t4 = new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class Resource1
{
private String  name;
private int count = 1;
private boolean flag = false;
private Lock lk = new ReentrantLock();
private Condition condition_pro = lk.newCondition();
// 一个锁可以对应多个condition对象。
private Condition condition_con = lk.newCondition();
public  void set(String name) throws InterruptedException
{
lk.lock();
try{
while(flag)
condition_pro.await();//t1 t2
this.name = name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"-生产者------"+this.name);
flag = true;
condition_con.signal();
}finally
{
lk.unlock();//释放锁的动作一定要执行,防止await产生异常造成死锁。
}
}
//t3 t4
public  void out() throws InterruptedException
{
lk.lock();
try
{
while(!flag)
condition_con.await();
System.out.println(Thread.currentThread().getName()+"-消费者-"+this.name);
flag = false;
condition_pro.signal();
}
finally
{
lk.unlock();
}
}
}
class Producer1 implements Runnable
{
private Resource1 re;
Producer1(Resource1 re)
{
this.re = re;
}
public void run()
{
while(true)
{
try {
re.set("+商品+");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer1 implements Runnable
{
private Resource1 re;
Consumer1(Resource1 re)
{
this.re = re;
}
public void run()
{
while(true)
{
try {
re.out();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}


----------------------
ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: