线程一些小知识的整理。
需求: 使用线程同步和通信,解决生产者和消费者的问题!
技能:
1.线程同步---推荐使用同步代码块(同步锁---建议使用共享资源)
2.实现多线程----推荐使用实现Runnable接口
3.通信的方法---三个方法
说明: 他们都存在Object类当中,因为Object类是任何的类的父类,子类都可以通过继承关系,继承三个通信的方法!
根据三个方法的定义,他们都使用了final修饰,也就是说,子类只能继承不能重写!
线程等待---wait()方法
特点:1.在线程等待的同时,释放同步锁!
2.只能等待另外一个线程的通知/唤醒,此线程才能继续运行!
笔试题: wait()方法和sleep()方法的异同! --- 作业题。
线程的唤醒----notify()方法
特点: 只能唤醒等待的线程,不能唤醒休眠的线程!
唤醒所有的线程---notifyAll()方法
特点: 唤醒所有正在等待的线程
对于正在等待的线程,那个线程优先级别高,就先唤醒谁!(谨记: 即使全部唤醒,同时线程的优先级高的线程,也不一定先执行!)
代码区:(重中之重)
public class Consumer implements Runnable {
//属性---成员变量
private Product pro;
//get set方法
public Product getPro() {
return pro;
}
public void setPro(Product pro){
this.pro = pro;
}
//构造方法
public Consumer() {
super();
}
public Consumer(Product pro) {
super();
this.pro = pro;
}
//重写run()方法
public void run() {
//消费产品
while(true){
//通过产品类对象,调用消费方法
pro.get();
}
}
}
public class Producer implements Runnable{
//定义属性---成员变量
private Product pro = null;
//get set方法
public Product getPro() {
return pro;
}
public void setPro(Product pro) {
this.pro = pro;
}
//构造方法
public Producer() {
super();
// TODO Auto-generated constructor stub
}
//目的: 为了防止出现空指针异常
public Producer(Product pro) {
super();
this.pro = pro;
}
//重写run方法
public void run() {
//定义一个变量 i 初始化值为0 目的: 为了区分生产馒头还是玉米饼 如果i%2==0 生产馒头,反之,生产玉米饼
int i =0;
//循环的进行生产,以便能生产馒头和玉米饼,如果不使用循环语句,则只会生产一次,而且只是馒头
while(true){
if(i%2==0){
pro.put("馒头", "白色");
}else{
pro.put("玉米饼", "黄色");
}
//改变if语句当中的布尔值,如果为true,则生产馒头,反之,生产玉米饼
i++;
}
}
}
/**
* Product类: 产品类
* 目的:1.使用此类对象,充当同步锁(同步监视器)
* 2.把产品的属性以及get set方法和构造方法,写入到此类,供以后使用
* 同时,把生产的方法和消费的方法,也写入到此类中!
* 原因: 在使用同步的时候,会调用这个两个方法!
*
* 生产馒头和玉米饼
* 馒头---白色
* 玉米饼---黄色
*/
public class Product {
//属性
private String name;
private String color;
//定义一个boolean类型的变量,目的: 为了在生产以及消费当中,进行判断而用
private boolean isProduct = false;
//get set方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
//构造方法
public Product() {
super();
}
public Product(String name, String color) {
super();
this.name = name;
this.color = color;
}
//toString()方法
@Override
public String toString() {
return "Product [name=" + name + ", color=" + color + "]";
}
//生产和消费的方法---要求这两个方法使用同步方法!
// 生产的方法,此方法的形参: 产品的名称和产品的颜色
public synchronized void put(String name,String color){
//1.1 先进性判断,消费者判断仓库当中是否有产品
if(isProduct){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//1.2 生产产品
this.name=name;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.color=color;
System.out.println(Thread.currentThread().getName()+"生产:"+name+" "+color);
//1.3 修改boolean类型的变量,目的: 说明仓库已经有产品了,不用再生产了
isProduct = true;
//1.4 唤醒消费者线程
notify();
}
//消费的方法
public synchronized void get(){
//1.1 判断
if(!isProduct){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//1.2 消费产品
System.out.println(Thread.currentThread().getName()+"消费产品:"+this.getName()+"---"+this.getColor());
//1.3 修改boolean变量的值
isProduct = false;
//1.4 唤醒生产者线程,进行生产
notify();
}
}
public class Test {
public static void main(String[] args) {
//1.创建产品类对象,目的: 为生产者线程和消费线程的构造方法做准备
Product pro = new Product();
//2.创建Runnalbe接口对象
Runnable r1 = new Producer(pro);
Runnable r2 = new Consumer(pro);
//3.借助Thread类,创建线程,并启动线程
Thread t1 = new Thread(r1,"生产者------");
Thread t2 = new Thread(r2,"消费者---");
t1.start();
t2.start();
}
}
原博地址(也是我,O(∩_∩)O哈哈~):http://m15231417197.lofter.com/
练习代码地址(嘿嘿嘿):https://download.youkuaiyun.com/download/m15231417197/10716486
本文深入探讨线程同步和通信技巧,通过生产者和消费者问题的实例,讲解如何使用同步代码块、实现Runnable接口及wait、notify方法,确保线程间的正确交互。

被折叠的 条评论
为什么被折叠?



