java Day12-14消费者与生产者pro & String

本文深入探讨了多线程环境下生产者与消费者模式的实现,对比了wait()与Condition对象在同步控制上的应用,并详细讲解了字符串及StringBuffer类的操作方法。

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

生产者与消费者

多线程参与,上一个线程生产一个产品,下一个线程就消费一个产品

class imformation
{
    private String name;
    private int rank=1;
    private boolean flag=false;
    public synchronized void setname(String name)
    {
        if(flag)
            try
            {
                this.wait();
            }
        catch (Exception e)
        {

        }
        this.name=name+"---"+rank++;
            System.out.println(Thread.currentThread().getName()+"..."+this.name);
            flag=true;
            this.notify();
    }
    public synchronized void show()
    {
        if(!flag)
            try
            {
                this.wait();
            }
            catch (Exception e)
            {

            }
        System.out.println(Thread.currentThread().getName()+"..."+name);
            flag=false;
            this.notify();
    }
}
class in implements Runnable
{
    private imformation s;
    in(imformation s)//有参数的构造函数传入imformation对象参数
    {
        this.s=s;
    }
    public void run()
    {
        while (true)
        s.setname("mark li");

    }
}
class out implements Runnable
{
    private imformation s;
    out(imformation s)//有参数的构造函数传入imformation对象参数
    {
        this.s=s;
    }
    public void run()
    {
        while(true)
        s.show();
    }
}
class day12
{
    public static void main(String[] args)
    {
        imformation s=new imformation();
        in a=new in(s);
        out b=new out(s);

        Thread t1=new Thread(a);
        Thread t2=new Thread(b);

        t1.start();
        t2.start();


    }
}

JDK1.5中替代wait() notify()的新方法:Condition对象和lock对象
新建Lock 对象lock,再调用子类lock的lock()方法,在线程开始时获取锁,然后新建Condition对象,格式为Condition name=lock.newCondition();线程进入后使用lock.lock();来获取锁,使用Condition对象中的await(); signal(); signalAll();方法来使线程等待,单唤醒与全唤醒。在线程代码的最后使用lock.unlock();来抛出锁,以便下一个线程进入。

1.建立对象

	private Lock lock=new ReentrantLock();
    private Condition condition1=lock.newCondition();
    private Condition condition2=lock.newCondition();

2.使用对象的方法

lock.lock();
        try
        {
            while(flag)
                condition1.await();
            this.name=name+"---"+rank++;
            System.out.println(Thread.currentThread().getName()+"..."+this.name);
            flag=true;
                condition1.signal();
        }
        catch (InterruptedException e)
        {

        }
        finally
        {
            lock.unlock();
        }

3.抛出异常
在方法上抛出异常。throws InterruptedException

停止线程

代替stop();的interrupt();方法
interrupt ()方法不是直接停止线程,而是将在冻结状态中的线程唤醒,继续运行run代码块中的代码,来结束这个线程。
在线程被冻结 或者被挂起时 interrupt方法唤醒他

class stopdemo implements Runnable
{
    private boolean flag=true;
    private int num=0;
    public synchronized void run()
    {
        while(flag)
        {
            try//线程等待但并未唤醒
            {
                wait();
            }
            catch (InterruptedException e)
            {
                System.out.println("Thread wrong!");
            }
            System.out.println(Thread.currentThread().getName() + " Thread come in"+num++);
            //无notify()方法,线程被冻结。
        }
    }
    public void changes()
    {
        flag=false;
    }
}
class day12
{
    public static void main(String[] args)
    {
        int num=0;

        stopdemo t=new stopdemo();
        Thread t1=new Thread(t);
        Thread t2=new Thread(t);
        Thread t3=new Thread(t);

        t1.start();
        t2.start();
        t3.start();

        while(true)
        {
            if(num==10)
            break;
            System.out.println("Main Thread runnning "+num++);
        }
        t.changes();
        System.out.println("Main Thread Stopped!");
        t1.interrupt();//唤醒
        t2.interrupt();//唤醒
        t3.interrupt();//唤醒
    }
}

在该程序中,跳出while循环的flag在主程序结束的时候已经被改变,但是由于线程被冻结,无法回到while条件判断处,线程冻结,程序不能继续运行。
主程序结束后, t1.interrupt(); t2.interrupt(); t3.interrupt();方法唤醒了冻结的线程,while条件判断跳出死循环,结束了这个线程。

守护线程

setDaemon();
守护线程必须在开启线程之前执行。
前台线程结束后,被守护的后台线程也自动结束。

join(); 使得线程拥有执行权。直至该线程执行结束。

Thread.yield(); 暂停当前线程,运行其他线程。

String类

字符串一旦被初始化就不能再改变。

   	String s1="abcdefgh";
    System.out.println(s1.length());//获取字符串长度
    System.out.println(s1.charAt(4));//获取指定位置的字符
    System.out.println(s1.indexOf("d"));//获取第一次出现指定字符的位置
    System.out.println(s1.indexOf("g",3));//从指定位置开始搜索,获取第一次出现指定字符的位置
    System.out.println(s1.lastIndexOf("g"));//从后往前搜索,获取指定字符的位置
    System.out.println(s1.startsWith("abc"));//判断字符串是否以指定字符串开头
    System.out.println(s1.endsWith("fgh"));//判断字符串是否以指定字符串结束
    System.out.println(s1.contains("def"));//判断字符串是否包含指定字符串
    System.out.println(s1.equals("abcdefgh"));//判断字符串是否相同,区别大小写
    System.out.println(s1.equalsIgnoreCase("ABCdeFgH"));//判断字符串是否相同,不区别大小写

转换

String(char[],num1.num2)将字符数组转换成字符串,由num1起到num2结束。
将字符串转化成字符数组

char[] arr=new char[10];
        String s1="abcd";
        arr=s1.toCharArray();
        System.out.println(arr.length);

将字符数组转换成字符串 String[] toString(str);

字符串的转换与切割

字符串的替换。
replace(char.char);
被替换的字符串不会改变。

		 String s1="ababcdef";
        System.out.println(s1.replace('a','g'));

字符串的切割:split(“mark”);以mark为标志切割字符串。

		String s1="aba,bcd,ef";
        String[] arr=new String[10];
        arr=s1.split(",");
        for(int i=0;i<arr.length;i++)
            System.out.println(arr[i]);

获取字符串的一部分
substring(num):从num开始获取字符串直至结束。
substring(num1,num2):从下表num1开始获取字符直到num2的前一个字符,即包含头不包含尾
如果num越界,则会报字符串越界的错误

转换字符串的大小写:
toUpwerCase():将字符串所有字符转换成大写
toLowerCase():将字符串所有字符转换成小写
trim():去除字符串的首部和尾部位的空格,不去掉中间的。
compareto(字符串),比较字符串,如果全部相同返回0,如果不同,一位一位比较,返回ASCII值差之和。

StringBuffer

StringBuffer是一个字符串缓冲区,是一个容器,无论你对这个对象进行如何的操作,他总是这一个对象,只是不断的更新。
StringBuffer的特点:
1.长度可变
2.可操作的数据类型多
3.操作结束后可以通过toSting转换成字符串类型。

对StringBuffer进行操作
1.添加数据
新建一个对象: StringBuffer op=new StringBuffer();
op.append( ):向容器中加入数据。
op.insert(index,?):向容器中插入数据,插入为为给定的角标。

	StringBuffer op=new StringBuffer("time is ");
        op.append("carsh").append("is time");
        sop(op);
        op.insert(1,"mad!");
        sop(op);

2.删除数据
delete();
deleteCharAt(3);l

		op.delete(1,3);//给定始末位置删除
        sop(op);
        sop(op.deleteCharAt(3));//删除指定位置的字符

3.替换数据
replace(index1,index2,“String”) 在给定的起 止角标替换成给定字符。
setCharAt(num,‘char’):将给定角标的字符替换成给定字符。这个方法的返回值类型不是StringBuffer 而是无返回值类型。

4.反转数据
reverse();将字符缓冲区反转。
void getChars(start,end,char【】,index):把数据从start开始,end-1结束,存入给定的char类型数组,存入时,从给定的index角标开始存储。

JDK1.5之后更新的StringBuilder,其方法与StringBuffer使用方法完全一致,但是在多线程的安全上StringBuffer更加安全。

基本数据类型包装类

作用:将各类数据转换为其他类型的数据
Integer.toString(int x) 把数字转换为String类常量。
Integer.parseInt() 将String类的数字转换成int类的常量。

JDK1.5之后的基本数据类型包装类的新特性:
在类型范围内 如果已经存在 那么新定义的变量就不会开辟新的空间,所以两个变量指向的是同一块内存区域。如果超过,就会开辟新的内存空间,两个变量指向的是不同的内存地址。

集合框架

为什么出现集合?
对存储对象的要求,数组只能储存同一种类型的对象,而集合可以存储各种类型的对象。

集合是用于存储对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值