多线程知识点3

如果对一块共享数据,多个线程做不同的操作,有读有写,就有必要进行线程通讯处理,以便提高效率。

一、线程通讯:

1、线程通讯的概念:
线程通讯指的是多个线程通过消息传递实现相互牵制,相互调度,即线程间的相互作用。


2、Java线程通讯的实现:
Java代码中基于对共享数据进行“wait()、notify()、notifyAll()”来实现多个线程的通讯。
 
经典例子:生产者和消费者的问题。
 
1)、Warehouse.java

<span style="font-size:18px;">import java.util.ArrayList;
import java.util.List;

/**
 * 仓库类,用储存商品,联系生产者和消费者
 * @author hanwen
 *
 */
public class Warehouse {
	
	//定义一个集合,用来存储生产的产品
	private List<String> products=new ArrayList<String>();
	
	
	/**
	 * 生产者生产商品,存储到仓库里
	 */
	public void addproduct(String stringname){
		products.add(stringname);//想仓库里面添加产品
	}
	
	/**
	 * 消费者消费商品
	 */
	public String getProduct(){
		//判断仓库是不是为空
		if(!products.isEmpty()){
			//从仓库中取产品,返回给消费者
			String stringname=products.remove(0);
			return stringname;
		}else{
			System.out.println("仓库为空,请及时生产产品...");
			return "";
		}
	}
	
	/**
	 * 获取库存余量
	 * 
	 * @return
	 */
	public int getSize(){
		//返回库存余量
		return products.size();
	}	
}</span>


2)、CustomerThread.java

<span style="font-size:18px;">/**
 * 消费者线程类
 * 
 * @author Administrator
 *
 */
public class CustomerThread implements Runnable {
	// 属性
	private Warehouse wh;      // 仓库对象
	private String name;       // 消费者姓名

	// 构造函数传递参数
	public CustomerThread(Warehouse wh, String name) {
		super();
		this.wh = wh;
		this.name = name;
	}

	// 消费产品
	@Override
	public void run() {

		while (true) {
			synchronized (wh) {
				if (wh.getSize() == 0) {
					try {
					    System.out.println("仓库为空,消费者" + name + "进入等待状态........");
						wh.wait();
						System.out.println("线程等待结束,重新启动");
						
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				} else if (wh.getSize() > 0) {
					// 取走商品,
					String stringname = wh.getProduct();
					System.out.println("消费者" + name + "取走了产品" + stringname);
				}
			}
			try {
				Thread.sleep(1500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}</span>


3)、ProductThread.java

<span style="font-size:18px;">import java.util.Random;

public class ProductThread implements Runnable {

	// 定义一个仓库对象
	private Warehouse wh;

	// 有参数的构造方法
	public ProductThread(Warehouse wh) {

		super();
		this.wh = wh;
	}

	/**
	 * 开始生产产品
	 */
	@Override
	public void run() {
		while (true) {
			// 自动的随机产生产品
			String stringname = "p" + (new Random()).nextInt(1000);

			synchronized (wh) {
				// 把产品放进仓库
				wh.addproduct(stringname);
				// 提示信息
				System.out.println("仓库里面已经存入商品" + stringname);
				//唤醒线程,让他继续执行
				//wh.notify();
				wh.notifyAll();
			}
			try {
				// 睡一会
				Thread.sleep(1500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}</span>


4)、TestDemo.java

<span style="font-size:18px;">/**
 * 测试类
 * @author Administrator
 *
 */
public class TestDemo {

	public static void main(String[] args) {
	 
	//实例化仓库对象
		Warehouse wh=new Warehouse();
		
		//实例化生产者对象
		ProductThread pt=new ProductThread(wh);
		//实例化消费者对象
		CustomerThread ct=new CustomerThread(wh,"小明");
		CustomerThread ct1=new CustomerThread(wh,"小花");
		CustomerThread ct2=new CustomerThread(wh,"小灰灰");
		CustomerThread ct3=new CustomerThread(wh,"小飞飞");
		
		//建线程类进行包装
		Thread t=new Thread(pt);
		Thread t2=new Thread(ct);
		Thread t3=new Thread(ct1);
		Thread t4=new Thread(ct2);
		Thread t5=new Thread(ct3);
		
		//启动线程
		t.start();
		t2.start();
		t3.start();
		t4.start();
		t5.start();
	}
}</span>

3、wait()、notify()、notifyAll() 方法:

   ①、final void notify()  唤醒在此对象监视器上等待的单个线程
   ②、final void notifyAll() 唤醒在此对象监视器上等待的所有线程
   ③、final void wait() throws InterruptedException 导致当前的线程等待,直到其他线程调用此对象的 notify()
          方法或 notifyAll() 方法
   ④、final void wait(long timeout) throws InterruptedException 导致当前的线程等待,直到其他线程调用此对
          象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量。
   ⑤、final void wait(long timeout, int nanos) throws InterruptedException 导致当前的线程等待,直到其他

          线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实

          际时间量。

   ⑥、wait() 和 notify() 方法(包括上述的所有方法,下同) 都是 Object 类的最终方法,所以每个类默认都拥有该方                  法。 为确保 wait() 和 notify() 的功能,在执行之前必须要先获得互斥锁,即一定要和 synchronized 一起使用。
           如 synchronized 的锁对象是 obj 的话,wait 和 notify 正确的使用方法是obj.wait()和obj.notify()。



4、sleep() 和 wait() 的区别:


                 sleep()                       wait()
            
属性           Thread的静态方法                            Object的方法


作用             让本线程进入睡眠状态                     让本线程进入等待状态


是否释放同步锁      不会释放同步所                                会释放同步所




5、线程死锁:


   ①、线程死锁指的两个线程互相持有对方依赖的共享资源,造成都无限阻塞。
   ②、导致死锁的根源在于不适当地运用“synchronized”关键词来管理线程对特定对象的访问。
   ③、解决死锁的方法:
                     让线程持有独立的资源。
               尽量不采用嵌套的 synchronized 语句。
    
6、线程状态转换:


   线程状态介绍
    1)、新建状态(New):使用 new 关键字创建线程对象,仅仅被分配了内存;
2)、可运行状态(Runnable):线程具备获得CPU时间片的能力。线程进入可运行状态的情况如下:

         ①、线程 start() 方法被调用;
         ②、当前线程 sleep()、其它线程 join() 结束、等待用户输入完毕;
         ③、某个线程取得对象锁;

         ④、当前线程时间片用完了,调用当前线程的 yield() 方法。


 3)、运行状态(Running):执行 run 方法,此时线程获得CPU的时间片;

         4)、阻塞状态(Blocked):线程由于某些事件放弃CPU使用权,暂停运行。直到线程重新进入可运行

                  状态,才有机会转到运行状态。阻塞状态分为如下几种:

      
   ①、同步阻塞 – 线程获得同步锁,若被别的线程占用,线程放入锁池队列中。
   ②、等待阻塞 – 线程执行 wait() 方法,线程放入等待队列中。

   ③、其它阻塞 – 线程执行 sleep() 或 join() 或发出 I/O 请求。


   5)、死亡状态(Dead):run、main() 方法执行结束,或者因异常退出了 run() 方法,线程进入死亡状

                  态,不可再次复生。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值