Java多线程9 多线程的提高

本文通过生产者与消费者模式探讨了多线程环境下资源的安全访问问题。介绍了如何使用同步机制来确保线程间的正确通信,避免资源覆盖及消费错位等问题。

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

之前的内容:理解多线程。创建多线程。多线程的安全问题/分析与理解。安全问题的解决办法/锁

———————————多线程的提高    线程之间的通信—————————————

之前的例子都是多个线程执行一个线程任务,多线程的提高——多个线程执行不同的线程任务,并发执行

例如:消费者与生产者,一个消费一个生产,执行的线程任务不同,但是处理的资源是一样的。但是要求同时进行

这叫做线程间的通信——你有你的动作,我有我的动作,但是处理的是同一个资源

初步代码:(执行有错误)

package Thread;
/*
线程的提升;生产者消费者问题
一个消费一个生产,执行的线程任务不同,但是处理的资源是一样的。但是要求同时进行
//线程间的通信
简化后的生产者和消费者——生产一个 消费一个
1.描述资源
2.描述生产者,具备自己的任务
3.描述消费者,具备自己的任务
 */
//描述资源——属性:名字,编号。行为:对商品名称赋值,获取商品
class Resource{//简化程序-设资源只有一个
    private String name;
    private int number=1;
    //提供设置方法
    public void set(String name ){
        //给成员变量赋值
        this.name = name+number;
        number++;
        //打印生产了那个商品
        System.out.println(Thread.currentThread().getName()+"    生产者    "+this.name);
    }
    //消费者的
    public void Out(){
        System.out.println(Thread.currentThread().getName()+"   消费者    "+this.name);
    }
}
class Producer implements Runnable{
    private Resource  r;
    Producer(Resource r){
        this.r = r;
    }
    public void run(){
        r.set("面包");
    }
}
//描述消费者
class consumer implements Runnable{
    private Resource r;
    consumer(Resource r){
        this.r=r;
    }
    public void run(){
        r.Out();
    }
}
public class producerAndConsumer {
    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();
    }
}

运行结果:有错误

加上一个小循环:

问题:这个程序的输出必须遵守,生产一个消费一个,正确的数据应该为:1 1 2 2 3 3 4 4 5 5.

————————————————解决问题/分析问题—————————————

以上两种错误情况是其中的两种,现在针对相应的错误做出解决方案:

1.很早被生产的商品(编号已经)被覆盖,才被消费到

输出结果:1 2 3 4 5 6(生产者)//1 .。。。(消费者)

按理说编号1 早已经被覆盖,不应该现在才被消费到

解决办法《这是线程的安全问题——使用同步   ——————解决了该问题

2.问题1 解决,但是又出现新的问题:有些商品不会被消费到(连续生产但是没有消费/对同一个商品进行多次消费):1 2 3 4 5 //(生产者)5 5 5 5//(消费者)

我们的希望应该是:生产一个消费一个

思考:什么时候生产————————盘子里没有商品时

什么时候消费————————————盘子里有商品时

设置标记

思路

正确的代码:

package Thread;
/*
线程的提升;生产者消费者问题
一个消费一个生产,执行的线程任务不同,但是处理的资源是一样的。但是要求同时进行
//线程间的通信
简化后的生产者和消费者——生产一个 消费一个
1.描述资源
2.描述生产者,具备自己的任务
3.描述消费者,具备自己的任务
 */
//描述资源——属性:名字,编号。行为:对商品名称赋值,获取商品
class Resource{//简化程序-设资源只有一个
    private String name;
    private int number=1;
    private boolean flag;
    //提供设置方法
    public synchronized void set(String name ){
        if(flag){//先判断
            try{wait();}catch(InterruptedException e){}//存在商品,此线程停止
        }
        else {
            //给成员变量赋值
            this.name = name + number;
            number++;
            //打印生产了那个商品
            System.out.println(Thread.currentThread().getName() + "    生产者    " + this.name);
            flag = true;//生产完,修改标志
            notify();//唤醒消费者
        }
    }
    //消费者的
    public synchronized void Out(){
        if(!flag){//先判断
            try{wait();}catch(InterruptedException e){}  //没有商品,消费者停止
        }
        System.out.println(Thread.currentThread().getName()+"   消费者    "+this.name);
        flag =false;//修改标记
        notify();//唤醒生产者
    }
}
//描述生产者
class Producer implements Runnable{
    private Resource  r;
    Producer(Resource r){
        this.r = r;
    }
    public void run(){
        for(int x=0;x<5;x++) {
            r.set("面包");
        }
    }
}
//描述消费者
class consumer implements Runnable{
    private Resource r;
    consumer(Resource r){
        this.r=r;
    }
    public void run(){
        for(int x=0;x<5;x++) {
            r.Out();
        }
    }
}
public class producerAndConsumer {
    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();
    }
}

总结:1.关于线程的提升——————线程间的的通信。其实有一点想的单例设计模式的需求和环境,但是单例设计的对象是强制唯一的,线程间的通信在此的要求没那么的苛刻,从代码上也能找到异同

2.关于等待和唤醒机制

资源下载链接为: https://pan.quark.cn/s/22ca96b7bd39 在 IT 领域,文档格式转换是常见需求,尤其在处理多种文件类型时。本文将聚焦于利用 Java 技术栈,尤其是 Apache POI 和 iTextPDF 库,实现 doc、xls(涵盖 Excel 2003 及 Excel 2007+)以及 txt、图片等格式文件向 PDF 的转换,并实现在线浏览功能。 先从 Apache POI 说起,它是一个强大的 Java 库,专注于处理 Microsoft Office 格式文件,比如 doc 和 xls。Apache POI 提供了 HSSF 和 XSSF 两个 API,其中 HSSF 用于读写老版本的 BIFF8 格式(Excel 97-2003),XSSF 则针对新的 XML 格式(Excel 2007+)。这两个 API 均具备读取和写入工作表、单元格、公式、样式等功能。读取 Excel 文件时,可通过创建 HSSFWorkbook 或 XSSFWorkbook 对象来打开相应格式的文件,进而遍历工作簿中的每个 Sheet,获取行和列数据。写入 Excel 文件时,创建新的 Workbook 对象,添加 Sheet、Row 和 Cell,即可构建新 Excel 文件。 再看 iTextPDF,它是一个用于生成和修改 PDF 文档的 Java 库,拥有丰富的 API。创建 PDF 文档时,借助 Document 对象,可定义页面尺寸、边距等属性来定制 PDF 外观。添加内容方面,可使用 Paragraph、List、Table 等元素将文本、列表和表格加入 PDF,图片可通过 Image 类加载插入。iTextPDF 支持多种字体和样式,可设置文本颜色、大小、样式等。此外,iTextPDF 的 TextRenderer 类能将 HTML、
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值