生产者与消费者
多线程参与,上一个线程生产一个产品,下一个线程就消费一个产品
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之后的基本数据类型包装类的新特性:
在类型范围内 如果已经存在 那么新定义的变量就不会开辟新的空间,所以两个变量指向的是同一块内存区域。如果超过,就会开辟新的内存空间,两个变量指向的是不同的内存地址。
集合框架
为什么出现集合?
对存储对象的要求,数组只能储存同一种类型的对象,而集合可以存储各种类型的对象。
集合是用于存储对象。