java基础补充
1、 ++和--参加混合运算
++在前 先自增 拿自增后的值参加本次运算
++在后 先进行本次运算 再自增
//++ --的混合运算
int a,b=2;
a=(++b)+b/(--b)+3*(b++)+b+b--;
//b=2 3 2 3 2
// 3+3/2 +3*2+3+3=3+1+6+3+3=
System.out.println(a+"::"+b);//16+2
//注意
int a=1;
a=a++;//此时a的值仍未1
a=++a;//此时a的值为2
2 、不定参数
public static void main(String[] args) {
//1.8的新特性:不定参数::基本等价于数组
test2(1,2,3,4);
test2(1);
test2();
test2(new int[]{1,2,3,4});
}
//int[] arr=new int[0];
static void test1(int[] arr){//方法参数:可以是n个int n>=0
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+(i==arr.length-1?"\n":","));
}
}
static void test2(int...n){//方法参数:可以是n个int n>=0
System.out.println(n);//[I@15db9742
}
// static void test2(int[] n){//方法参数:可以是n个int n>=0
// System.out.println(n);//[I@15db9742
// }
static void test3(long l,int...n){//方法参数:可以是n个int n>=0
System.out.println(n);//[I@15db9742
}
// static void test4(int...n,float f){//不定参数必须是最后一个参数
// System.out.println(n);//[I@15db9742
// }
//输出的话,把n当成数组遍历就行啦
3、代码块
//类的组成
class Test{
//1 实例变量
int a;
//2 类变量
static int b;//共享数据
//3 实例方法
void show(){}
//4 类方法
static void hehe(){}//如果一个方法没有涉及实例成员 尽量写成类方法
//5 构造方法
Test(){}
//6内部类
class Inner{}
//7构造代码块:每创建对象时 都执行一次:
// 构造代码块 一般用于给对象的实例变量初始化
{
a=1;
System.out.println("构造代码块---------");
}
//8 静态代码块:只有在类加载时 执行一次
//静态代码块一般用于给类变量初始化
static{
b=1;
System.out.println("静态代码块---");
}
}
//即使new很多次对象,类加载的代码块也只会执行一次
//但是调用静态方法,静态方法可以执行多次,静态方法可以不用实例化之间类名.方法调用就行
4、 字符串缓冲区(重点)
- 方法
* String,StringBuffer,StringBuilder
* String:字符串常量 字符序列不能更改
* StringBuffered和StringBuilder:字符串缓冲区 字符序列可以更改
* 相同之处:都可以描述字符串
* 不同之处: String:字符串常量 字符串对象一旦创建 字符序列不能更改
* StringBuffer和StringBuilder:都是字符串缓冲区 字符长度和字符序列都可以更改
* StringBuffer和StringBuilder都是字符串缓冲区 API兼容(方法完全相同)
* 版本不同:StringBuilder 1.5 StringBuffer 1.0
* 是否同步:StringBuilder线程不同步 只支持单线程 线程不安全 效率高
* StringBuffer线程同步 支持多线程 线程安全 效率低
*
* 构造方法:
* StringBuffer() :创建一个初始序列为空的字符串缓冲区对象
StringBuffer(String str) :创建一个与初始字符串相同序列的字符串缓冲区对象
普通方法:
和String相同的方法:
char charAt(int index) :获取参数下标出的字符
int indexOf(String str) :获取参数字串第一次出现的位置 如果找不到返回-1
int indexOf(String str, int fromIndex) :从fromIndex位置处开始 获取参数字串第一次出现的位置 如果找不到返回-1
int lastIndexOf(String str) :倒着找
int lastIndexOf(String str, int fromIndex)
int length() :获取字符个数
CharSequence subSequence(int start, int end) :截取字串:start到end-1处的字符
String substring(int start) :截取字串:start到末尾的字符
String substring(int start, int end) 截取字串:start到end-1处的字符
字符串缓冲区特有的方法: 以下方法返回都是当前字符串缓冲区对象
StringBuffer append(Object obj) :把参数对象对应的字符串添加到末尾
StringBuffer delete(int start, int end):删除start到end-1处的字符
StringBuffer deleteCharAt(int index) :删除index下标出的字符
StringBuffer insert(int offset, Object obj) : 把obj对应的字符串插入到offset下标处
StringBuffer replace(int start, int end, String str) :使用str替换start到end-1位置处的子串
StringBuffer reverse() :字符串序列翻转
void setCharAt(int index, char ch): 设置index下标处的字符为ch
String toString():获取当前字符串缓冲区相同序列的字符串对象
- 练习
public static void main(String[] args) {
StringBuilder stb=new StringBuilder("abcdefghijk");
StringBuilder stb2=stb.append("lm");
//append方法返回的是当前字符串缓冲区对象 可以实现方法链
//stb.append("lm").append(1).append(2).append(true);
System.out.println(stb==stb2);//true
System.out.println(stb);//abcdefghijklm
System.out.println(stb.delete(1, 3));//adefghijklm
stb=new StringBuilder("abcdefghijk");
System.out.println(stb.deleteCharAt(1));//acdefghijk
stb=new StringBuilder("abcdefghijk");
System.out.println(stb.insert(1, "haha"));//ahahabcdefghijk
stb=new StringBuilder("abcdefghijkbc");
System.out.println(stb.replace(1, 3, "123456"));//a123456defghijkbc
System.out.println(stb.reverse());//cbkjihgfed654321a
stb=new StringBuilder("abcdefghijk");
stb.setCharAt(1, '0');
System.out.println(stb);//a0cdefghijk
}
public static String change(String s){
//使用字符串缓冲区实现字符串的转换:大小写转换 删除数字
StringBuilder stb=new StringBuilder(s);//把字符串转换为字符串缓冲区
for (int i = 0; i <stb.length(); i++) {
//获取当前字符
char c=stb.charAt(i);
//判断当前字符的类型
if(Character.isUpperCase(c)){
c=Character.toLowerCase(c);
stb.setCharAt(i, c);
}else if(Character.isLowerCase(c)){
c=Character.toUpperCase(c);
stb.setCharAt(i, c);
}else if(Character.isDigit(c)){
//删除当前字符
stb.deleteCharAt(i);
i--;
}
}
return stb.toString();
}
5 、LinkedList(重点)
/*
*LinkedList是List的实现类
*底层是链表
*使用和Arraylist基本相同 都可以根据下标操作元素 但提供了更多的对头和尾的操作
* void addFirst(E e) :在头部添加元素
void addLast(E e) :在尾部添加元素
E getFirst() :获取头部的第一个元素
E getLast() :获取尾部的最后一个元素
E pollFirst() :移除并返回头部的第一个元素 如果链表为空 返回null
E pollLast() :移除并返回尾部的最后一个元素 如果链表为空 返回null
E removeFirst() :移除并返回头部的第一个元素 如果链表为空 抛异常NoSuchElementException
E removeLast() :移除并返回尾部的最后一个元素 如果链表为空 抛异常NoSuchElementException
LinkedList和ArrayList的区别
一: 底层实现不同:ArrayList底层是可变长度数组的实现 LinkedList底层是链表
二: ArrayList元素在内存中是连续空间 而 LinkedList的元素内存空间可以不连续 可以实现内容的有效利用
三: ArrayList查询和修改效率高 但增删效率低 LinkedList增删效率高 但查询和修改效率低
* */
public static void main(String[] args) {
LinkedList<String> list=new LinkedList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
list.addFirst("0");
list.addLast("1");
for (int i = 0; i <list.size(); i++) {
System.out.print(list.get(i)+(i==list.size()-1?"\n":","));
}
}
5、TreeSet
- 方法
* TreeSet: 不重复 元素按自然顺序排序
* 方法:继承与Collection
* 特有方法:
* E first() :获取第一个元素
E last() :获取最后一个元素
E floor(E e) :获取小于等于参数的最大元素 如果不存在这样的元素,则返回 null。
E ceiling(E e) :获取大于等于参数的最小元素 如果不存在这样的元素,则返回 null。
E higher(E e) :获取大于参数的最小元素 如果不存在这样的元素,则返回 null。
E lower(E e) : 获取小于参数的最大元素 如果不存在这样的元素,则返回 null。
E pollFirst(): 移除并返回第一个元素
E pollLast() :移除并返回最后一个元素
- 实现类的可比较性
package com.zhiyou100.day15_buchong;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
public class Demo06TreeSet {
/*
*怎么保证一个类的对象具有可比较性:
* 方案1: 让类实现Comparable<E>接口 实现public int compareTo(E o) 方法
* 方案2:为类创建一个比较器类 实现Comparator<E> 实现public int compare(E o1, E o2)
* 注意:在使用TreeSet时需要关联一个比较器对象:new TreeSet<>(new Student062Compartor());
*
* */
public static void main(String[] args) {
TreeSet<Student06> set2=new TreeSet<>();
set2.add(new Student06("韩梅梅", 12, 17.8f));//java.lang.ClassCastException
set2.add(new Student06("韩庚", 22, 27.8f));
set2.add(new Student06("韩庚", 22, 27.8f));
set2.add(new Student06("韩雪", 32, 27.8f));
set2.add(new Student06("韩雪1", 32, 27.8f));
set2.add(new Student06("韩雪2", 32, 27.8f));
set2.add(new Student06("韩非子", 12, 17.8f));
set2.add(new Student06("韩信", 22, 27.8f));
Iterator<Student06> it2=set2.iterator();
while(it2.hasNext()){
System.out.println(it2.next());
}
TreeSet<Student062> set3=new TreeSet<>(new Student062Compartor());
set3.add(new Student062("韩梅梅", 12, 17.8f));//java.lang.ClassCastException
set3.add(new Student062("韩庚", 22, 27.8f));
set3.add(new Student062("韩庚", 22, 27.8f));
set3.add(new Student062("韩雪", 32, 27.8f));
set3.add(new Student062("韩雪1", 32, 25.8f));
set3.add(new Student062("韩雪2", 32, 26.8f));
set3.add(new Student062("韩非子", 12, 17.8f));
set3.add(new Student062("韩信", 22, 27.8f));
set3.add(new Student062("韩信1", 22, 27.8f));
set3.add(new Student062("韩信2", 22, 27.8f));
Iterator<Student062> it3=set3.iterator();
while(it3.hasNext()){
System.out.println(":::::::::"+it3.next());
}
}
}
class Student06 implements Comparable<Student06>{
String sname;
int sage;
float score;
@Override
public String toString() {
return "Student06 [sname=" + sname + ", sage=" + sage + ", score=" + score + "]";
}
public Student06(String sname, int sage, float score) {
this.sname = sname;
this.sage = sage;
this.score = score;
}
public Student06() {
super();
}
//拿读取对象和参数对象做比较:当前对象大 返回正数 当前对象小 返回负数 相同返回0
public int compareTo(Student06 o) {
//按自己的要求返回:分数高的大 分数相同 年龄小的大 年龄相同 名字大的大
if(o.score!=this.score){
return this.score>o.score?1:-1;
}
if(o.sage!=this.sage){
return o.sage-this.sage;
}
return this.sname.compareTo(o.sname);
}
}
class Student062{
String sname;
int sage;
float score;
@Override
public String toString() {
return "Student06 [sname=" + sname + ", sage=" + sage + ", score=" + score + "]";
}
public Student062(String sname, int sage, float score) {
this.sname = sname;
this.sage = sage;
this.score = score;
}
}
class Student062Compartor implements Comparator<Student062>{
@Override
public int compare(Student062 o1, Student062 o2) {
//年龄小的大 年龄相同 分数小的大 分数相同 名字小的大
if(o1.sage!=o2.sage){
return o1.sage-o2.sage;
}
if(o1.score!=o2.score){
return o2.score<o1.score?1:-1;
}
return o1.sname.compareTo(o2.sname);
}
}
6、集合工具类:Collections
/*
* Collections:集合工具类
* 提供了操作Collection的static方法
* static void fill(List list, T obj) : 使用参数对象obj替换list中的所有元素
static T max(Collection coll) :获取最大的元素
static T min(Collection coll) :获取最小的元素
static T max(Collection coll, Comparator comp) :按制定比较器 获取最大的元素
static T min(Collection coll, Comparator comp) :按制定比较器 获取最小的元素
static void reverse(List<?> list) :反转
static void shuffle(List<?> list) :随机洗牌
static void sort(List<T> list) :排序
static void sort(List<T> list, Comparator<? super T> c) :按参数比较器 排序
static void swap(List<?> list, int i, int j) :下标i和下标j处的元素互换位置
* */
public static void main(String[] args) {
ArrayList list=new ArrayList();
list.add("123");list.add("1");list.add("2");
list.add("abd");list.add("abc");list.add("abc");
show(list);
//Collections.fill(list, "abc");//使用abc替换list中的所有元素
//Collections.reverse(list);//集合元素反转
//Collections.shuffle(list);//洗牌
//Collections.sort(list);//排序
Collections.swap(list, 1, 2);//1 和 2 位置处的元素互换值
show(list);
}
public static void show(List list){
for (int i = 0; i <list.size(); i++) {
System.out.print(list.get(i)+(i==list.size()-1?"\n":","));
}
}
7、数组工具类:Arrays
/*
* Arrays:数组工具类:static操作数组的方法
* static <T> List<T> asList(T... a):由参数数组获取一个集合
* static void fill(boolean[] a, boolean val) :使用val填充数组a
static void sort(char[] a) :对数组a进行排序
static <T> void sort(T[] a, Comparator<? super T> c) :按比较器c对数组a进行排序
static String toString(boolean[] a) :获取参数数组的字符串
* */
public static void main(String[] args) {
String[] arr={"1a","12","1b","21","31","122"};
List<String> list=Arrays.asList(arr);
list=Arrays.asList("1a","12","1b","21","31","122");
show(list);
System.out.println(Arrays.toString(arr));//[1a, 12, 1b, 21, 31, 122]
}
public static void show(List list){
for (int i = 0; i <list.size(); i++) {
System.out.print(list.get(i)+(i==list.size()-1?"\n":","));
}
}
- 游戏:明7拍 暗7过
/*明7拍暗7过*/
//由n个猴子围成一圈,从1开始数数 数到7的倍数的猴子被踢出去 问最后的那个猴子是大王 他的编号是几
public static int getDaiWang(int n){
//定义一个boolean数组 装所有猴子
Boolean[] arr=new Boolean[n];
//把所有值转化为true
Arrays.fill(arr, true);
//定义变量记录被踢出去的猴子的个数
int count=0;
//定义变量记录叫的数
int num=0;
//一直遍历数组
while(true){
if(count==n-1){
break;
}
for(int i=0;i<arr.length;i++){
if(arr[i]){
num++;//叫数
if(num%7==0){
//当前元素被踢出去
arr[i]=false;
count++;
if(count==n-1){
break;
}
}
}
}
}
//获取唯一的true
List<Boolean> list=Arrays.asList(arr);
int index1=list.indexOf(true)+1;
//int index2=list.lastIndexOf(true)+1;
//System.out.println(index1+"::"+index2);
return index1;
}
8、打印输出流:PrintWriter(重点)
/*PrintWriter:打印输出流
* 特点1:既可以作为节点流还可以作为过滤流
* PrintWriter(File file)
PrintWriter(OutputStream out)
* 特点2:可以保证数据的原始状态
* pout.print(49);等价于 fout.write(49+"");
*
* 特点3:当创建对象时指定自动刷新 调用println是可以实现自动刷新
*
* */
public static void main(String[] args)throws Exception {
FileWriter fout=new FileWriter("src/com/zhiyou100/day15_buchong/1.txt");
fout.write("abc");
fout.write(49);//
fout.write(true+"");
//fout.flush();
//fout.close();
PrintWriter pout=new PrintWriter(new FileWriter("src/com/zhiyou100/day15_buchong/2.txt"),true);
pout.println("abc");
pout.println(49);
pout.println(true);
//pout.flush();
//pout.close();
}
9、序列化流(重点)
- 介绍
* 序列化相关的类:把内存中对象的信息持久化保存到硬盘中 把硬盘中的信息重构成内存中的对象
* ObjectInputStream:反序列化流 把硬盘中的信息读到内存中 重构成对象
* ObjectOutputStream:序列化流: 把内存中对象的信息持久化保存到硬盘上
*
* ObjectOutputStream类的方法:
* ObjectOutputStream(OutputStream out) :构造方法关联一个字节流
* void writeObject(Object obj) :把一个对象的信息写到目的文件中
*
*ObjectInputStream类的方法:
* ObjectInputStream(InputStream in):构造方法关联一个字节流
* Object readObject() :一次读一个对象的信息 并重构对象
*
*
* 注意事项:
* 1 序列化流和反序列化流 操作的对象必须实现接口Serializable
* 2 ObjectInputStreamd的readObject()读到文件末尾 抛出异常EOFException
* 3 Serializable接口会给当前类分配一个唯一的编号 用于保证序列化和反序列化使用的同一个接口
* 4 序列化流不支持续写
* UUID:通用唯一识别码(Universally Unique Identifier)
* 随机一个 32位的16进制的字符串
- 代码实现
public static void main(String[] args)throws Exception{
// for (int i = 0; i < 10; i++) {
// System.out.println(UUID.randomUUID().toString());
// }
ArrayList<Student> list=new ArrayList<>();
// for (int i = 0; i <10; i++) {
// list.add(new Student());
// }
// System.out.println(list);
// saveObject(list,"src/com/zhiyou100/day15_buchong/student1.obj");
createObject("src/com/zhiyou100/day15_buchong/student1.obj");
}
//把student1.obj中的信息重构成对象
public static void createObject(String fileName)throws Exception{
//1创建字节流关联源文件
//2 创建反序列化流与节点流关联
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(fileName));
//3 选择读的方式:逐个对象的读
while(true){
try{
Student s=(Student)ois.readObject();
System.out.print(s);
}catch(EOFException e){
break;
}
}
//4关闭流
ois.close();
}
//把list中的对象持久化保存到文件中
public static void saveObject(ArrayList<Student> list,String fileName)throws Exception{
//1 创建字节流关联目的文件
FileOutputStream fout=new FileOutputStream(fileName);
//2 创建序列化流与节点流关联
ObjectOutputStream oos=new ObjectOutputStream(fout);
//3 现在写方式:逐个对象的写
for (Student s : list) {
oos.writeObject(s);
}
//4关闭流
oos.close();
// [Student [sname=6cc4, sex=女, score=73.9]
// , Student [sname=d476, sex=女, score=73.9]
// , Student [sname=ba03, sex=男, score=52.4]
// , Student [sname=f7f9, sex=女, score=54.3]
// , Student [sname=5343, sex=女, score=48.4]
// , Student [sname=bda8, sex=女, score=57.6]
// , Student [sname=aef0, sex=男, score=68.8]
// , Student [sname=1bc1, sex=女, score=59.9]
// , Student [sname=e9c7, sex=男, score=84.6]
// , Student [sname=e10f, sex=男, score=54.9]
}
}
//Exception in thread "main" java.io.InvalidClassException: com.zhiyou100.day15_buchong.Student; local class incompatible: stream classdesc serialVersionUID = -5497088744421407018, local class serialVersionUID = -630471015205919448
class Student implements Serializable{
//为当前类分配一个唯一编号
private String sname;
char sex;
float score;
public Student(){
sname=UUID.randomUUID().toString().replace("-", "").substring(0, 4);
sex=Math.random()>0.5?'男':'女';
score=(int)(Math.random()*1001)/10.0f;
}
@Override
public String toString() {
return "Student [sname=" + sname + ", sex=" + sex + ", score=" + score + "]\n";
}
}
10 、创建线程的方式
参考https://www.cnblogs.com/zhou-test/p/9811771.html
创建线程的四种方式
package com.zhiyou100.day15_buchong;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
public class Demo12CreateThread {
public static void main(String[] args)throws Exception{
//test01();
//test02();
//test03();
//test04();
// //1 创建runnbale接口的实现类
// //2实现run方法
// //3 创建线程池对象 并制定线程个数
// ExecutorService threadPool=Executors.newFixedThreadPool(10);
// //4 创建实现类对象
// MyImp04 imp=new MyImp04();
// //5 通过线程池对象的sumbit方法 提交线程任务:提交的次数 就是运行的线程个数
// for (int i = 0; i <5; i++) {
// threadPool.submit(imp);
// }
// //6关闭池对象
// threadPool.shutdown();
//
//
// MyThread01 mt=new MyThread01();mt.setName("线程1111");
// mt.start();
//未解决问题:把创建线程卸载方法中 main线程不能达到同步的效果
for (int i = 0; i < 50; i++) {
int n=(int)(Math.random()*10);
try {Thread.sleep(100);} catch (Exception e) {}
System.out.println(Thread.currentThread().getName()+" :"+i+"::n="+n);
}
}
//方式1: 继承Thread 重写run方法
public static void test01(){
MyThread01 mt=new MyThread01();mt.setName("线程1111");
mt.start();
}
//方式2:实现Runnable接口 实现run方法
public static void test02(){
MyImp02 i2=new MyImp02();
Thread t=new Thread(i2,"线程22222");
t.start();
}
//方式3:实现Callable接口 实现call方法 创建FutureTask对象
public static void test03()throws Exception{
MyCall03 mc=new MyCall03();//创建callable实现类对象
FutureTask<Integer> task=new FutureTask<>(mc);//创建futuretask对象并关联callable实现类对象
Thread t=new Thread(task);t.setName("线程3333333333");//创建线程对象 并关联futuretask对象
t.start();//开启线程
//获取线程的返回值
int sum=task.get();
System.out.println("sum="+sum);
}
//方式4:线程池: 线程池提供了一个线程队列,队列中保存着所有等待状态的线程。避免了创建与销毁额外开销,提交了响应速度。
// 创建Runnable的实现类 通过Executors创建线程池对象 通过池对象的submit方法来启动一个线程
public static void test04()throws Exception{
//1 创建runnbale接口的实现类
//2实现run方法
//3 创建线程池对象 并制定线程个数
ExecutorService threadPool=Executors.newFixedThreadPool(10);
//4 创建实现类对象
MyImp04 imp=new MyImp04();
//5 通过线程池对象的sumbit方法 提交线程任务:提交的次数 就是运行的线程个数
for (int i = 0; i <5; i++) {
threadPool.submit(imp);
}
//6关闭池对象
threadPool.shutdown();
}
}
class MyThread01 extends Thread{
public void run(){
for (int i = 0; i < 50; i++) {
int n=(int)(Math.random()*10);
try {Thread.sleep(100);} catch (Exception e) {}
System.out.println(Thread.currentThread().getName()+" :"+i+"::n="+n);
}
}
}
class MyImp02 implements Runnable{
public void run(){
for (int i = 0; i < 50; i++) {
int n=(int)(Math.random()*10);
try {Thread.sleep(100);} catch (Exception e) {}
System.out.println(Thread.currentThread().getName()+" :"+i+"::n="+n);
}
}
}
//实现Callable接口 接口的泛型是返回值类型
class MyCall03 implements Callable<Integer>{
//1 可以有返回值 2 可以抛出异常
public Integer call() throws Exception {
int sum=0;
for (int i = 0; i < 50; i++) {
int n=(int)(Math.random()*10); sum+=n;
try {Thread.sleep(100);} catch (Exception e) {}
System.out.println(Thread.currentThread().getName()+" :"+i+"::n="+n);
}
return sum;
}
}
class MyImp04 implements Runnable{
public void run(){
for (int i = 0; i < 50; i++) {
int n=(int)(Math.random()*10);
try {Thread.sleep(100);} catch (Exception e) {}
System.out.println(Thread.currentThread().getName()+" :::::"+i+"::n="+n);
}
}
}
11、 wait和notify
package com.zhiyou100.day15_buchong;
public class Demo13WaitNotify {
/*
* 面试题:wait和sleep的区别
* wait和notify都是锁对象的方法
* Object类的方法: void wait() 当前线程等待
* Object类的方法: void notify() 随机唤醒一个当前对象作为锁对象 并且处于等待状态的线程
* Object类的方法: void notifyAll() 唤醒所有当前对象作为锁对象 并且处于等待状态的线程
*武大郎做烧饼 猪八戒吃烧饼
*1 实现做和吃不干扰::做和吃两个线程
* */
public static void main(String[] args) {
// TODO Auto-generated method stub
ShaoBing shb=new ShaoBing();
Provider p1=new Provider(shb,"武大郎");
Provider p2=new Provider(shb,"武二郎");
Consumer c1=new Consumer(shb, "猪八戒");
Consumer c2=new Consumer(shb, "沙僧");
c1.start();
c2.start();
p1.start();
p2.start();
}
}
class ShaoBing{
int num=0;
boolean blag=false;//定义一个标签 记录当前是否有烧饼
}
class Provider extends Thread{
ShaoBing shb;
public Provider(ShaoBing shb,String name) {
super(name);
this.shb = shb;
}
public void run(){
while(true){
synchronized (shb) {
if(shb.blag==false){
System.out.println(Thread.currentThread().getName()+"开始做烧饼::"+(shb.num+1));
shb.num++;
try {Thread.sleep(200);} catch (Exception e) {}
System.out.println(Thread.currentThread().getName()+"做完烧饼::"+(shb.num));
//提醒猪八戒 可以吃烧饼
shb.blag=true;
shb.notifyAll();//唤醒猪八戒:唤醒一个shb相同锁 并且处于等待状态的线程
}else{
try {shb.wait();} catch (Exception e) {}//当前线程等待
}
}
try {Thread.sleep(20);} catch (Exception e) {}
}
}
}
class Consumer extends Thread{
ShaoBing shb;
public Consumer(ShaoBing shb,String name) {
super(name);
this.shb = shb;
}
public void run(){
while(true){
synchronized (shb) {
if(shb.blag){
System.out.println(Thread.currentThread().getName()+"开始吃烧饼::::::"+(shb.num));
try {Thread.sleep(20);} catch (Exception e) {}
System.out.println(Thread.currentThread().getName()+"吃烧饼完成::::::"+(shb.num));
shb.blag=false;//烧饼标签值更改
shb.notifyAll();//唤醒武大郎
}else{
try {shb.wait();} catch (Exception e) {}//当前线程等待
}
}
try {Thread.sleep(20);} catch (Exception e) {}
}
}
}