本章概述:本章主要讲了线程基础内容,线程同步,线程间通信以及多线程在Java中的运用
目录
本章概述:
一、api
1、JoinDemo
package com.tensent.class4.api;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/15 - 04 - 15 - 11:32
* @Description: com.tensent.class4.api
* @version: 1.0
*/
public class JoinDemo {
public static void main(String[] args) {
RunDemo runDemo = new RunDemo();
Thread thread = new Thread(runDemo);
thread.start();
for (int i = 0; i < 10; i++) {
if(i == 3){
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "------------" + i);
}
}
}
2、RunDemo
package com.tensent.class4.api;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/15 - 04 - 15 - 11:31
* @Description: com.tensent.class4.api
* @version: 1.0
*/
public class RunDemo implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "------------" + i);
}
}
}
3、SleepDemo
package com.tensent.class4.api;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/15 - 04 - 15 - 11:36
* @Description: com.tensent.class4.api
* @version: 1.0
*/
public class SleepDemo {
public static void main(String[] args) {
RunDemo runDemo = new RunDemo();
Thread thread = new Thread(runDemo);
thread.start();
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "------------" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
4、StopDemo
package com.tensent.class4.api;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/15 - 04 - 15 - 11:40
* @Description: com.tensent.class4.api
* @version: 1.0
*/
public class StopDemo {
public static void main(String[] args) {
RunDemo runDemo = new RunDemo();
Thread thread = new Thread(runDemo);
thread.start();
for (int i = 0; i < 100; i++) {
if(i == 2){
thread.stop();
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "------------" + i);
}
}
}
5、ThreadApiDemo
package com.tensent.class4.api;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/15 - 04 - 15 - 11:19
* @Description: com.tensent.class4.api
* @version: 1.0
*/
public class ThreadApiDemo {
public static void main(String[] args) {
//获取当前线程的实例
Thread thread = Thread.currentThread();
//获取当前线程的名称
System.out.println(thread.getName());
//获取线程的优先级,一般情况优先级是0-10之间的整数,默认优先级是5,特殊情况下也可以是0-100之间的整数。
/*
* 作用:
* 数值越大代表优先级越高,但是优先级越高并不一定意味着它会被先执行,而是说优先级高的会执行的效率更大一些,仅此而已。
*/
System.out.println(thread.getPriority());
}
}
6、YieldDemo
package com.tensent.class4.api;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/15 - 04 - 15 - 11:40
* @Description: com.tensent.class4.api
* @version: 1.0
*/
public class YieldDemo {
public static void main(String[] args) {
RunDemo runDemo = new RunDemo();
Thread thread = new Thread(runDemo);
thread.start();
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "------------" + i);
if(i == 6){
//线程礼让一次,进入就绪状态,如果就绪队列中没有其他线程或者其他线程没有它自己抢占CPU资源快的话,那么它自己会快读的抢占CPU资源进行运行状态。
Thread.yield();
}
}
}
}
二、proxy
1、JiaShi
package com.tensent.class4.proxy;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/15 - 04 - 15 - 10:50
* @Description: com.tensent.class4.proxy
* @version: 1.0
*/
public class JiaShi implements KindWomen {
@Override
public void makeEyesWithMen() {
System.out.println("贾氏抛媚眼... ...");
}
@Override
public void playWithMen() {
System.out.println("贾氏... ...");
}
}
2、KindWomen
package com.tensent.class4.proxy;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/15 - 04 - 15 - 10:45
* @Description: com.tensent.class4.proxy
* @version: 1.0
*/
public interface KindWomen {
/*
* 抛媚眼
*/
public void makeEyesWithMen();
public void playWithMen();
}
3、PanJinLian
package com.tensent.class4.proxy;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/15 - 04 - 15 - 10:47
* @Description: com.tensent.class4.proxy
* @version: 1.0
*/
public class PanJinLian implements KindWomen {
@Override
public void makeEyesWithMen() {
System.out.println("潘金莲抛媚眼... ..");
}
@Override
public void playWithMen() {
System.out.println("潘金莲... ...");
}
}
4、WangPo
package com.tensent.class4.proxy;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/15 - 04 - 15 - 10:46
* @Description: com.tensent.class4.proxy
* @version: 1.0
*/
public class WangPo implements KindWomen {
private KindWomen kindWomen;
public WangPo(){
this.kindWomen = new PanJinLian();
}
public WangPo(KindWomen kindWomen){
this.kindWomen = kindWomen;
}
@Override
public void makeEyesWithMen() {
this.kindWomen.makeEyesWithMen();
}
@Override
public void playWithMen() {
this.kindWomen.playWithMen();
}
}
5、XiMenQing
package com.tensent.class4.proxy;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/15 - 04 - 15 - 10:47
* @Description: com.tensent.class4.proxy
* @version: 1.0
*/
public class XiMenQing {
public static void main(String[] args) {
// WangPo wangPo = new WangPo();
// wangPo.makeEyesWithMen();
// wangPo.playWithMen();
JiaShi jiaShi = new JiaShi();
WangPo wangPo = new WangPo(jiaShi);
wangPo.makeEyesWithMen();
wangPo.playWithMen();
}
}
三、ThreadDemo
1、ThreadDemo
package com.tensent.class4.threadDemo;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/13 - 04 - 13 - 17:29
* @Description: com.tensent.class4.threadDemo
* @version: 1.0
*/
/**
* 实现多线程的两种方式:
* 第一种实现方式:继承Thread类
* 1、需要继承Thread类
* 2、必须要重写run方法,指的是核心执行的逻辑
* 3、线程在启动的时候,不要直接调用run方法,而是要通过start()来进行调用
* 4、每次运行相同的代码,出来的结果可能不一样,原因在于多线程谁先抢占资源无法进行人为控制
* 第二种实现方式:使用了代理设计模式
* 1、实现Runnable接口
* 2、重写run方法
* 3、创建Thread对象,将刚刚创建好的runnable的子类实现作为thread的构造参数
* 4、通过thread.start()进行启动
* 两种实现方式哪种用的比较多
* 推荐使用第二种方式,
* 1、java是单继承,将继承关系留给最需要的类
* 2、使用runnable接口之后不需要给共享变量添加static关键字,每次创建一个对象,作为共享对象即可
* 线程的生命周期:
* 1、新生状态(新建状态):
* 当创建好当前线程对象之后,没有启动之前(调用start方法之前)
* ThreadDemo thread = new ThreadDemo()
* RunnableDemo run = new RunnableDemo()
* 2、就绪状态:准备开始执行,并没有执行,表示调用start方法之后
* 当对应的线程创建完成,且调用start方法之后,所有的线程会添加到一个就绪队列中,所有的线程同时去抢占cpu的资源
* 3、运行状态:当当前进程获取到cpu资源之后,就绪队列中的所有线程会去抢占cpu的资源,谁先抢占到谁先执行,在执行的过程中就叫做运行状态
* 抢占到cpu资源,执行代码逻辑开始
* 4、死亡状态:当运行中的线程正常执行完所有的代码逻辑或者因为异常情况导致程序结束叫做死亡状态
* 进入的方式:
* 1、正常运行完成且结束
* 2、人为中断执行,比如使用stop方法
* 3、程序抛出未捕获的异常
* 5、阻塞状态:在程序运行过程中,发生某些异常情况,导致当前线程无法再顺利执行下去,此时会进入阻塞状态,进入阻塞状态的原因消除之后,
* 所有的阻塞队列会再次进入到就绪状态中,随机抢占cpu的资源,等待执行
* 进入的方式:
* sleep方法
* 等待io资源
* join方法(代码中执行的逻辑)
*
* 注意:
* 在多线程的时候,可以实现唤醒和等待的过程,但是唤醒和等待操作的对应不是thread类
* 而是我们设置的共享对象或者共享变量
* 多线程并发访问的时候回出现数据安全问题:
* 解决方式:
* 1、同步代码块
* synchronized(共享资源、共享对象,需要是object的子类){具体执行的代码块}
* 2、同步方法
* 将核心的代码逻辑定义成一个方法,使用synchronized关键字进行修饰,此时不需要指定共享对象
*
*/
public class ThreadDemo {
public static void main(String[] args) {
/*
一个java程序运行的步骤:
1、编写java源文件,源程序;
2、使用javac命令编译.java文件,生成对应的.class字节码文件
3、使用java命令解释执行.class文件中存在的类
*/
for(int i = 0; ;i++){
System.out.println("hello!");
}
}
}
四、ticket
1、RunnableTicket
package com.tensent.class4.ticket;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/15 - 04 - 15 - 10:34
* @Description: com.tensent.class4.ticket
* @version: 1.0
*
* 出现的问题:
* 1、卖票的次序是混乱的;
* 2、每个窗口不能平均的卖票,分配不均,有些窗口卖了很多票,有些窗口一张票都没卖。这个不符合显示情况。
*
*/
public class RunnableTicket implements Runnable {
//资源(火车票)
private int ticket = 10;
@Override
public void run() {
for(int i =0; i <100;i++){
if(ticket > 0){
System.out.println(Thread.currentThread().getName() + "----------正在卖第" + (ticket--) +"张票!");
}
}
}
public static void main(String[] args) {
RunnableTicket runnableTicket = new RunnableTicket();
Thread t1 = new Thread(runnableTicket,"1号窗口");
Thread t2 = new Thread(runnableTicket,"2号窗口");
Thread t3 = new Thread(runnableTicket,"3号窗口");
Thread t4 = new Thread(runnableTicket,"4号窗口");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
2、RunnableTicket2
package com.tensent.class4.ticket;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/15 - 04 - 15 - 10:34
* @Description: com.tensent.class4.ticket
* @version: 1.0
* <p>
* 出现的问题:
* 1、卖票的次序是混乱的;
* 2、每个窗口不能平均的卖票,分配不均,有些窗口卖了很多票,有些窗口一张票都没卖。这个不符合显示情况。
*/
public class RunnableTicket2 implements Runnable {
//资源(火车票)
private Integer ticket = 10;
// String str = "";
@Override
public void run() {
//定义一个共同的锁
/*
当多个线程共同访问同一个资源的时候,会出现线程安全问题,此时解决办法之一是加锁,
在java中要求锁是对象类型,任何对象都是可以的,但是需要保证多个线程访问的是同一把锁。
程序中锁的名称特别的锁:
1、锁旗标;
2、同步监视器;
3、同步锁;
4、互斥锁;
5、对象锁;
6、锁
... ...
*/
// String str = "";
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (ticket) {
// synchronized (this){
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + "----------正在卖第" + (ticket--) + "张票!");
}
}
}
}
public static void main(String[] args) {
RunnableTicket2 runnableTicket = new RunnableTicket2();
Thread t1 = new Thread(runnableTicket, "1号窗口");
Thread t2 = new Thread(runnableTicket, "2号窗口");
Thread t3 = new Thread(runnableTicket, "3号窗口");
Thread t4 = new Thread(runnableTicket, "4号窗口");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
3、RunnableTicket3
package com.tensent.class4.ticket;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/15 - 04 - 15 - 10:34
* @Description: com.tensent.class4.ticket
* @version: 1.0
* <p>
* 出现的问题:
* 1、卖票的次序是混乱的;
* 2、每个窗口不能平均的卖票,分配不均,有些窗口卖了很多票,有些窗口一张票都没卖。这个不符合显示情况。
*/
public class RunnableTicket3 implements Runnable {
//资源(火车票)
private int ticket = 10;
@Override
public void run() {
//定义一个共同的锁
/*
当多个线程共同访问同一个资源的时候,会出现线程安全问题,此时解决办法之一是加锁,
在java中要求锁是对象类型,任何对象都是可以的,但是需要保证多个线程访问的是同一把锁。
程序中锁的名称特别的锁:
1、锁旗标;
2、同步监视器;
3、同步锁;
4、互斥锁;
5、对象锁;
6、锁
... ...
*/
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.sale();
}
}
public synchronized void sale() {
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + "----------正在卖第" + (ticket--) + "张票!");
}
}
public static void main(String[] args) {
RunnableTicket3 runnableTicket = new RunnableTicket3();
Thread t1 = new Thread(runnableTicket, "1号窗口");
Thread t2 = new Thread(runnableTicket, "2号窗口");
Thread t3 = new Thread(runnableTicket, "3号窗口");
Thread t4 = new Thread(runnableTicket, "4号窗口");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
4、ThreadTicket
package com.tensent.class4.ticket;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/15 - 04 - 15 - 10:17
* @Description: com.tensent.class4.ticket
* @version: 1.0
*
* 模拟4个窗口卖共同的10张火车票
*
* 出现的问题:
* 1、不是在共享10张票的资源,而是各个窗口在卖自己的10张票,出现这种情况的原因每次都new的新的线程,此时ticket变量是和对象相关的,所以对应的就有了4个10张票出现;
* 2、卖票的次序是有问题的。
*
*/
public class ThreadTicket extends Thread {
//资源(火车票)
private static int ticket = 10;
public ThreadTicket(String threadName){
super(threadName);
}
@Override
public void run() {
for(int i =0; i <100;i++){
if(ticket > 0){
System.out.println(Thread.currentThread().getName() + "----------正在卖第" + (ticket--) +"张票!");
}
}
}
public static void main(String[] args) {
ThreadTicket t1 = new ThreadTicket("1号窗口");
ThreadTicket t2 = new ThreadTicket("2号窗口");
ThreadTicket t3 = new ThreadTicket("3号窗口");
ThreadTicket t4 = new ThreadTicket("4号窗口");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
五、thread
1、RunnableDemo
66package com.tensent.class4.thread;
import com.tensent.class2.ticket.ThreadTicket;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/13 - 04 - 13 - 17:57
* @Description: com.tensent.class4.thread
* @version: 1.0
*/
public class RunnableDemo implements Runnable {
@Override
public void run() {
for(int i = 0; i<10;i++){
System.out.println(Thread.currentThread().getName() + "------" + i);
}
}
public static void main(String[] args) {
//创建线程对象
RunnableDemo runnableDemo = new RunnableDemo();
//启动线程---使用java中的设计模式(代理模式)
Thread thread = new Thread(runnableDemo);
thread.start();
for(int i = 0; i<10;i++){
System.out.println(Thread.currentThread().getName() + "------" + i);
}
}
}
2、ThreadDemo
package com.tensent.class4.thread;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/13 - 04 - 13 - 17:47
* @Description: com.tensent.class4.thread
* @version: 1.0
*/
public class ThreadDemo extends Thread {
public ThreadDemo(String threadName){
super(threadName);
}
@Override
public void run() {
for(int i = 0; i<10;i++){
System.out.println(Thread.currentThread().getName() + "run()------" + i);
}
}
public static void main(String[] args) {
//创建线程对象
ThreadDemo threadDemo = new ThreadDemo("自定义线程");
System.out.println(threadDemo.isAlive());
//启动线程
threadDemo.start();
System.out.println(threadDemo.isAlive());
// threadDemo.run();
//获取线程的优先级,一般情况优先级是0-10之间的整数,默认优先级是5,特殊情况下也可以是0-100之间的整数。
// System.out.println(threadDemo.getPriority());
//修改优先级为10
// threadDemo.setPriority(10);
for(int i = 0; i<10;i++){
System.out.println(Thread.currentThread().getName() + "main()------" + i);
}
System.out.println(threadDemo.isAlive());
}
}
六、producerAndConsumerDemo
1、producerAndConsumer
(1)、Consumer
package com.tensent.class4.producerAndConsumer;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/16 - 04 - 16 - 15:58
* @Description: com.tensent.class4.producerAndConsumer
* @version: 1.0
*
* 消费者从共享区域中取商品(拿走商品)
*/
public class Consumer implements Runnable {
private Goods goods;
public Consumer(Goods goods) {
this.goods = goods;
}
@Override
public void run() {
for(int i = 0; i<10;i++){
System.out.println("消费者消费了================================" + goods.getBrand() + "=========" + goods.getName());
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
(2)、Goods
package com.tensent.class4.producerAndConsumer;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/16 - 04 - 16 - 15:53
* @Description: com.tensent.class4.producerAndConsumer
* @version: 1.0
*
* 生产者和消费者共享的资源:商品
*
*/
public class Goods {
private String brand;
private String name;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
(3)、Producer
package com.tensent.class4.producerAndConsumer;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/16 - 04 - 16 - 15:54
* @Description: com.tensent.class4.producerAndConsumer
* @version: 1.0
*
* 生产者负责生产商品
*/
public class Producer implements Runnable {
private Goods goods;
public Producer(Goods goods) {
this.goods = goods;
}
@Override
public void run() {
for(int i = 0; i <10 ;i++){
//交替生产哇哈哈矿泉水和旺仔小馒头
if(i % 2 == 0){
goods.setBrand("娃哈哈");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
goods.setName("矿泉水");
}else{
goods.setBrand("旺仔");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
goods.setName("小馒头");
}
System.out.println("生产者生产了-----------" + goods.getBrand() + "---" + goods.getName());
}
}
}
(4)、Test1
package com.tensent.class4.producerAndConsumer;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/16 - 04 - 16 - 16:00
* @Description: com.tensent.class4.producerAndConsumer
* @version: 1.0
*
* 测试类
*
* 出现问题:
* 1、生产者未生产,消费者已经消费了;
* 2、连续生产连续消费;
* 3、商品的两个属性,品牌和名称不能正确的对应。
*/
public class Test1 {
public static void main(String[] args) {
Goods goods = new Goods();
Producer producer = new Producer(goods);
Consumer consumer = new Consumer(goods);
Thread t1 = new Thread(producer);
Thread t2 = new Thread(consumer);
t1.start();
t2.start();
}
}
2、producerAndConsumer2
(1)、Consumer
package com.tensent.class4.producerAndConsumer2;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/16 - 04 - 16 - 15:58
* @Description: com.tensent.class4.producerAndConsumer
* @version: 1.0
*
* 消费者从共享区域中取商品(拿走商品)
*/
public class Consumer implements Runnable {
private Goods goods;
public Consumer(Goods goods) {
this.goods = goods;
}
@Override
public void run() {
for(int i = 0; i<10;i++){
goods.get();
}
}
}
(2)、Goods
package com.tensent.class4.producerAndConsumer2;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/16 - 04 - 16 - 15:53
* @Description: com.tensent.class4.producerAndConsumer
* @version: 1.0
* <p>
* 生产者和消费者共享的资源:商品
*/
public class Goods {
private String brand;
private String name;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//生产商品的方法
public synchronized void set(String brand, String name) {
this.setBrand(brand);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.setName(name);
System.out.println("生产者生产了-----------" + this.getBrand() + "---" + this.getName());
}
//消费商品的方法
public synchronized void get() {
System.out.println("消费者消费了================================" + this.getBrand() + "=========" + this.getName());
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
(3)、Producer
package com.tensent.class4.producerAndConsumer2;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/16 - 04 - 16 - 15:54
* @Description: com.tensent.class4.producerAndConsumer
* @version: 1.0
*
* 生产者负责生产商品
*/
public class Producer implements Runnable {
private Goods goods;
public Producer(Goods goods) {
this.goods = goods;
}
@Override
public void run() {
for(int i = 0; i <10 ;i++){
//交替生产哇哈哈矿泉水和旺仔小馒头
if(i % 2 == 0){
goods.set("娃哈哈","矿泉水");
}else{
goods.set("旺仔","小馒头");
}
}
}
}
(4)、Test1
package com.tensent.class4.producerAndConsumer2;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/16 - 04 - 16 - 16:00
* @Description: com.tensent.class4.producerAndConsumer
* @version: 1.0
*
* 测试类
*
* 出现问题:
* 1、生产者未生产,消费者已经消费了;
* 2、连续生产连续消费;
* 3、商品的两个属性,品牌和名称不能正确的对应。----解决了,使用同步方法解决的
*/
public class Test1 {
public static void main(String[] args) {
Goods goods = new Goods();
Producer producer = new Producer(goods);
Consumer consumer = new Consumer(goods);
Thread t1 = new Thread(producer);
Thread t2 = new Thread(consumer);
t1.start();
t2.start();
}
}
3、producerAndConsumer3
(1)、Consumer
package com.tensent.class4.producerAndConsumer3;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/16 - 04 - 16 - 15:58
* @Description: com.tensent.class4.producerAndConsumer
* @version: 1.0
*
* 消费者从共享区域中取商品(拿走商品)
*/
public class Consumer implements Runnable {
private Goods goods;
public Consumer(Goods goods) {
this.goods = goods;
}
@Override
public void run() {
for(int i = 0; i<10;i++){
goods.get();
}
}
}
(2)、Goods
package com.tensent.class4.producerAndConsumer3;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/16 - 04 - 16 - 15:53
* @Description: com.tensent.class4.producerAndConsumer
* @version: 1.0
* <p>
* 生产者和消费者共享的资源:商品
*/
public class Goods {
private String brand;
private String name;
//定义一个标志位,来表示共享区域中是否存在商品
private boolean isFull;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//生产商品的方法
public synchronized void set(String brand, String name) {
/*
如果生产者线程获取对应cpu资源,得到了执行机会,此时先判断共享区域中是否存在商品,如果已经存在了,那么当前生产者线程
进入阻塞状态,等待消费者来消费,反之如果共享区域中不存在商品,那么生产商品就可以了。
*/
if (isFull) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.setBrand(brand);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.setName(name);
System.out.println("生产者生产了-----------" + this.getBrand() + "---" + this.getName());
//如果程序能执行到此处,说明已经生产商品完毕了,此时需要标志位为true
isFull = true;
//唤醒消费者前来消费
notify();
}
//消费商品的方法
public synchronized void get() {
/*
如果消费者线程获取到对应的cpu时间片,获取到了执行机会了,此时先判断共享区域中是否存在商品,如果不存在商品,当前真正执行的消费者
线程进入阻塞状态,等待生产者生产商品,反之如果已经存在商品,那么消费者直接消费就可以了。
*/
if (!isFull) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("消费者消费了================================" + this.getBrand() + "=========" + this.getName());
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
//如果程序运行到此处,说明消费者已经消费完毕,需要修改标志位为false
isFull = false;
//唤醒生产者生产商品
notify();
}
}
(3)、Producer
package com.tensent.class4.producerAndConsumer3;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/16 - 04 - 16 - 15:54
* @Description: com.tensent.class4.producerAndConsumer
* @version: 1.0
*
* 生产者负责生产商品
*/
public class Producer implements Runnable {
private Goods goods;
public Producer(Goods goods) {
this.goods = goods;
}
@Override
public void run() {
for(int i = 0; i <10 ;i++){
//交替生产哇哈哈矿泉水和旺仔小馒头
if(i % 2 == 0){
goods.set("娃哈哈","矿泉水");
}else{
goods.set("旺仔","小馒头");
}
}
}
}
(4)Test1
package com.tensent.class4.producerAndConsumer3;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/16 - 04 - 16 - 16:00
* @Description: com.tensent.class4.producerAndConsumer
* @version: 1.0
*
* 测试类
*
* 出现问题:
* 1、生产者未生产,消费者已经消费了;
* 2、连续生产连续消费;
* 3、商品的两个属性,品牌和名称不能正确的对应。----解决了,使用同步方法解决的
*/
public class Test1 {
public static void main(String[] args) {
Goods goods = new Goods();
Producer producer = new Producer(goods);
Consumer consumer = new Consumer(goods);
Thread t1 = new Thread(producer);
Thread t2 = new Thread(consumer);
t1.start();
t2.start();
}
}
4、producerAndConsumer4
(1)、Consumer
package com.tensent.class4.producerAndConsumer2;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/16 - 04 - 16 - 15:58
* @Description: com.tensent.class4.producerAndConsumer
* @version: 1.0
*
* 消费者从共享区域中取商品(拿走商品)
*/
public class Consumer implements Runnable {
private Goods goods;
public Consumer(Goods goods) {
this.goods = goods;
}
@Override
public void run() {
for(int i = 0; i<10;i++){
goods.get();
}
}
}
(2)、Goods
package com.tensent.class4.producerAndConsumer4;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/19 - 04 - 19 - 15:00
* @Description: com.tensent.class4.producerAndConsumer4
* @version: 1.0
*
* 共享资源:商品
*/
public class Goods {
private String brand;
private String name;
public Goods(String brand, String name) {
this.brand = brand;
this.name = name;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
(3)、ProducerQueue
package com.tensent.class4.producerAndConsumer4;
import java.util.concurrent.BlockingQueue;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/19 - 04 - 19 - 15:01
* @Description: com.tensent.class4.producerAndConsumer4
* @version: 1.0
*
* 生产者队列
*/
public class ProducerQueue implements Runnable {
//阻塞式队列
private BlockingQueue<Goods> blockingQueue;
public ProducerQueue(BlockingQueue<Goods> blockingQueue) {
this.blockingQueue = blockingQueue;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
Goods goods = null;
if(i % 2 == 0){
goods = new Goods("娃哈哈","矿泉水");
}else{
goods = new Goods("旺仔","小馒头");
}
System.out.println("生产者生产了商品--------" +goods.getBrand() + "----" + goods.getName());
//把生产者生产的商品放入到队列中存储
try {
blockingQueue.put(goods);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
(4)、Test1
package com.tensent.class4.producerAndConsumer4;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
/**
* @Auther: Yu Panpan
* @Date: 2022/4/19 - 04 - 19 - 15:08
* @Description: com.tensent.class4.producerAndConsumer4
* @version: 1.0
*/
public class Test1 {
public static void main(String[] args) {
BlockingQueue<Goods> blockingQueue = new ArrayBlockingQueue<Goods>(5);
ProducerQueue producerQueue = new ProducerQueue(blockingQueue);
ConsumerQueue consumerQueue = new ConsumerQueue(blockingQueue);
new Thread(producerQueue).start();
new Thread(consumerQueue).start();
}
}
文章评论