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

本文探讨了ASP.Net、Android、iOS开发技术,并分享了.NET培训经验,涉及线程间通讯、多线程操作及停止线程原理。通过实例展示了如何使用同步和Lock锁实现生产者-消费者模式,以及停止线程的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

--------------------- 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培训、期待与您交流! ----------------------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值