多线程知识点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() 方法,线程进入死亡状

态,不可再次复生。

时间: 2024-10-08 00:27:51

多线程知识点3的相关文章

Java 多线程知识点整理

1.如何停止一个正在运行的线程? 使用共享变量,用volatile变量修饰,线程循环去访问该变量.如果线程因为发生某些事件进行阻塞,可以使用Thread的interrupt方法.可以使一个被阻塞的线程抛出一个中断异常,从而使线程提前结束阻塞状态,退出堵塞代码. class MyThread extends Thread { volatile boolean stop = false; public void run() { while (!stop) { System.out.println(g

java多线程知识点

下面是我学习多线程记录的知识点,并没详细讲解每个知识点,只是将重要的知识点记录下来,有时间可以看看,如果有不对的地方,欢迎大家支出,谢谢! 1.多线程的状态和创建方式:     线程的状态:          1.新状态:线程对象已经创建,还没有在其上调用start()方法.          2.可运行状态:当线程有资格运行,但调度程序还没有把它选定为运行线程时线程所处的状态.当start()方法调用时,线程首先进入可运行状态.在线程运行之后或者从        阻塞.等待或睡眠状态回来后,也

Java中多线程知识点总结

Java中有一个比较重要的知识点是多线程,废话就不说了,直接进入多线程的知识点.对多线程我们需要了解和知道一下的知识点:多线程的实现,多线程的安全性,多线程的线程通信,守护线程和线程的优先级等知识点. 首先,我想写点我对多线程的一点认识,其中说的语言不会很官方,但是我相信里面绝对没有坑,不会把大家带到歧途上去的.首先多线程的出现是为了更好的利用计算机的资源,提高程序的响应速度.多线程的运行由操作系统来控制,多核和单核的cpu执行同一个多线程程序的过程可能会不同,在单核中多线程程序只能在单核之间切

多线程知识点总结

1.创建线程的2种方法 方式1:继承java.lang.Thread类,并覆盖run()方法.优势:编写简单:劣势:无法继承其他父类 方式2:实现java.lang.Runnable接口,并实现run()方法.优势:可以继承其他类,多线程可以共享同一个Thread对象:劣势:编程方式稍微复杂,如需访问当前线程,需调用Thread.currentThread()方法 2. Java创建线程后,调用start()方法和run()的区别 两种方法的区别 1) start: 用start方法来启动线程,

java多线程知识点总结

1.线程调度知识:线程类Thread的了解,几个thread的方法.thread.sleep(),thread.join().(调用join方法的那个线程会立刻执行). object.wait()方法,notifyAll()方法. 2.线程间通信知识(共享资源):synchronized,volatile,readWriteLock,生产者消费者存储模型.队列.消息队列. 队列也算共享资源的访问啊.加锁在哪里加?(在共享对象里加锁) 3.实际中用到的地方:1.多线程访问缓存(数据队列,有生产者消

java多线程知识点汇总(四)多线程知识点脉络图

1.多线程安全问题 1)synchronized关键字:如何加锁的问题,选择synchronized方法还是synchnized代码块. 选择哪个锁问题,this对象,还是class对象(针对static方法或者变量),或者object对象 推荐使用同步代码块,因为加锁灵活,可以自己选择使用哪个锁,尤其一个类里面有多个同步方法时. 读写问题,保证多线程对同一对象的读写正常,不至于读到脏数据.读写方法共用同一个锁. 共享资源,这又涉及到单例模式的线程安全问题,线程池等. 2)线程安全类,比如str

多线程知识点(二)

1:互斥锁,只有一个线程进行(例如:读写)操作 2.栈区上面的对象随时可能销毁,ARC下block会自动保存到堆区 //NSGlobalBlock全局区(未使用局部变量) //    void (^task)() = ^{ //        NSLog(@"task"); //    }; //    NSLog(@"%@",task); // //    int a = 6; //    //NSStackBlock  栈区上面的对象随时可能会被销毁 //   

java多线程知识点概述

这里只起一个概述的作用,极其简单的列一下知识点,需要在脑海中过一下,如果哪些方面不熟悉的话,建议利用网络资源去学习. 1.线程.进程概念 概念 线程状态及其转换 2.死锁.预防.解决 3.jdk线程实现方式 继承Thread重写run方法.实现Runnable实现run方法.实现Callable重写call方法 call方法能抛出异常允许有返回值 join/jield/interrupt/stop/wait/sleep/setDaemon/suspend 4.线程同步.线程异步 同步使用场景:共

java多线程知识点汇总(二)---多线程实例解析

本实验主要考察多线程对单例模式的操作,和多线程对同一资源的读取,两个知识.实验涉及到三个类: 1)一个pojo类Student,包括set/get方法. 2)一个线程类,设置student的成员变量age和name的值为111和111 3)另一个线程类,设置student的成员变量age和name的值为222和2222 4)main类,for循环200次,分别创建200个线程1和线程2对同一资源访问.(共400个线程) 1.第一种情况:饿汉式单例模式保证多线程操控的是同一对象 //饿汉式单例模式

多线程知识点之NSThread的使用

/********线程的状态**************************************/ 线程的状态:新建状态(New)--->就绪状态(Runnable)----->运行状态(Running)---->阻塞状态(Blocked)---->死亡状态(Dead) 启动线程 - (void)start; // 进入就绪状态 -> 运行状态.当线程任务执行完毕,自动进入死亡状态 阻塞(暂停)线程 + (void)sleepUntilDate:(NSDate *)d