java学习随手笔记(更新)

java学习随手笔记(更新)

注: 该笔记中的知识点不具备连续性,这是我在学习Java中随手记下的东西,该笔记不是事无巨细的将所有的知识点一一记录,只是记录了我在听课过程中自我感觉需要记录的知识点。故此笔记不具备参考价值,如果您看到了这篇笔记,请将此略过。
向上转型是为了参数类型的统一
向下转型是为了调用子类中的特殊方法
工厂模式
工厂模式,耦合,
代理设计模式
在这里插入图片描述
在这里插入图片描述

包和访问控制权限

  • import语句只能出现在package语句之下,class定义的语句之上。
  • 但是,在idea里编辑时却没有这些问题,不晓得是什么原因。
    有时设置set classpath不起作用,可以看一下cmd的表头是不是有系统无法在消息文件中为 Application 找到消息号为 0x2350 的消息文本。如果有这个的话,应该在win+r里面直接控制cmd,这样问题才会解决
    jar的一些命令
用法: jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files ...
选项:
    -c  创建新档案
    -t  列出档案目录
    -x  从档案中提取指定的 (或所有) 文件
    -u  更新现有档案
    -v  在标准输出中生成详细输出
    -f  指定档案文件名
    -m  包含指定清单文件中的清单信息
    -n  创建新档案后执行 Pack200 规范化
    -e  为捆绑到可执行 jar 文件的独立应用程序
        指定应用程序入口点
    -0  仅存储; 不使用任何 ZIP 压缩
    -P  保留文件名中的前导 '/' (绝对路径) 和 ".." (父目录) 组件
    -M  不创建条目的清单文件
    -i  为指定的 jar 文件生成索引信息
    -C  更改为指定的目录并包含以下文件
如果任何文件为目录, 则对其进行递归处理。
清单文件名, 档案文件名和入口点名称的指定顺序
与 'm', 'f' 和 'e' 标记的指定顺序相同。

示例 1: 将两个类文件归档到一个名为 classes.jar 的档案中:
       jar cvf classes.jar Foo.class Bar.class
示例 2: 使用现有的清单文件 'mymanifest' 并
           将 foo/ 目录中的所有文件归档到 'classes.jar' 中:
       jar cvfm classes.jar mymanifest -C foo/ .

比如说我要把包cn整成一个jar文件,我可以这样写
jar -cvf my.jar cn
这样就会生成一个jar文件。
比如我要看my.jar的内容,我应该
jar -tvf my.jar 会出现像下面这样的目录结构

 0 Fri Jan 31 16:34:48 CST 2020 META-INF/
    69 Fri Jan 31 16:34:48 CST 2020 META-INF/MANIFEST.MF
     0 Fri Jan 31 16:34:20 CST 2020 cn/
     0 Fri Jan 31 16:34:20 CST 2020 cn/suyuesheng/
     0 Fri Jan 31 16:34:20 CST 2020 cn/suyuesheng/demo/
   406 Fri Jan 31 16:34:20 CST 2020 cn/suyuesheng/demo/Demo.class

要解压my.jar就用jar -xf my.jar
注意,使用jar文件前必须设置CLASSPATH

  • java的访问控制权限
  • java的访问控制权限的表格
序号 范围 private default protexted public
1 同一类
2 同一包中的类
3 不同包中的子类
4 其他包中的类

命名规范

一、命名规范
1、项目名全部小写,就是如果项目名是多个英语单词组成的,每个单词都要全部小写。
如:doubanssm。
2、包名全部小写。
3、类名首字母大写,也就是帕斯卡命名法,首字母大写,如果类名是多个单词拼成的,每个单词的首字母都要大写。
4、变量名、方法名首字母小写,也就是驼峰命名法,如果名称有多个单词组成,每个单词的首字母都要大写。
如:public int testJava(){}
5、常量名全部大写
如:public static final int ANIMAL_NUMBER=15;
二、命名规则
1、名称只能由字母、数字、下划线、$符号组成
2、不能以数字开头
3、名称不能使用JAVA中的关键字。
4、坚决不允许出现中文及拼音命名。

异常的处理流程

在这里插入图片描述

package cn.suyuesheng.errordemo;
//error 的标准用法
class MyMath{
    public int div(int i,int j) throws Exception{//异常交给调用处
        System.out.println("开始计算>>>>>>>>>>>>>>");
        int temp=0;
        try{
            temp=i/j;
        }catch (Exception e){//捕捉异常
            throw e;//抛出异常,异常到了方法这里,随即到了方法调用出
        }finally {
            System.out.println("计算结束>>>>>>>>>>>>>>>>");
        }
        return temp;
    }
}
//自定义异常
class MyException extends Exception{
    public MyException(String msg){
        super(msg);
    }
}
public class ErrorLaw001 {
    public static void main(String[] args) {
        try{
            System.out.println(new MyMath().div(12,3));
        }catch (Exception e){
            e.printStackTrace();
        }
        //
        System.out.println(">-----------------------");
        //检测自定义
        try{
            throw new MyException("haha");
        }catch (MyException e){
            e.printStackTrace();
            System.out.println(e);
        }
    }
}

在这里插入图片描述
选择工作区,eciplse中所有的项目都是以工作区为主的,一个工作区中包含多个项目
eclipse的所有配置都是以工作区为主的。每一个工作区的配置都是独立的。如果发现某一个工作区坏了(或者说你的工作区被整的乱七八糟了),重开一个工作区,一切都会好的
JDT的使用(重点
在这里插入图片描述

jdk1.5新特性

package cn.suyuesheng.new01;

//java1.5 新特性
public class HelloDemo {
	public static void main(String[] args) {
		System.out.println(add(new int[] {1,2,3,354,54524,3}));
		System.out.println(">================");
		System.out.println(addone(1,2,3,4345,45,232453,2435,42534));//这样就能直接输入整形数据
		System.out.println(addForEach(1,2,3,4,5,6,7,8,9,10));
	}

	/**
	 * 实现多个数据类型的累加操作
	 * 
	 * @param data 使用数组完成接收
	 * @return 多个整形数据累加的结果
	 */
	public static int add(int data[]) {
		int sum = 0;
		for(int i=0;i<data.length;i++) {
			sum+=data[i];
		}
		return sum;
	}
	/**
	 * 实现多个数据类型的累加操作,利用java1.5新特性
	 * @param arg
	 * @return
	 */
	public static int addone(int... arg) {
		int sum=0;
		for(int i=0;i<arg.length;i++) {
			//参数定义的形式变了,但是参数的访问没有改变
			sum+=arg[i];
		}
		return sum;
	}
	/**
	 * java1.5新特性 , foreach使数组的输出更为方便
	 * @param arg
	 * @return
	 */
	public static int addForEach(int...arg) {
		int sum=0;
		for(int x : arg) {
			sum+=x;
		}
		return sum;
	}
}

泛型

package cn.suyuesheng.fanxing;
//泛型的目的是解决向下转型的安全隐患
class Point<T> {// T是自定义的泛型标识
	private T x;// 此变量的类型由外部确定
	private T y;

	public T getX() {
		return x;
	}

	public void setX(T x) {
		this.x = x;
	}

	public T getY() {
		return y;
	}

	public void setY(T y) {
		this.y = y;
	}

	public String toString() {
		return "Point [x=" + x + ", y=" + y + "]";
	}

}

public class FanXingDemoOne {
	/**
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		Point<Integer> x = new Point<Integer>();// T类型自动变为Integer
		x.setX(30);// 这时用到了自动封装
		x.setY(20);// 这时用到了自动封装
		System.out.println("(" + x.getX().intValue() + "," + x.getY().intValue() + ")");
		Point<String> pp = new Point<String>();
		pp.setX("东经10");
		pp.setY("北纬25");
		System.out.println(pp.toString());
//		ありがとう
		Point<Integer> cp = new Point<>();// JDK1.7之后可以这样设置
		Point cf = new Point();// 这样默认设置类型为Object
		cf.setX(14);
		cf.setX(49);
		System.out.println((Integer) cf.getX());
		System.out.println(">++++++++++++++");
		cp.setX(12);
		cp.setY(16);
		System.out.println(cp.toString());
	}

}

一个类中多个泛型的情况👇

package cn.suyuesheng.fanxing;

public class FanXingDemoTwo<T, V> {// 指定多个泛型类型
	private T age;
	private V name;

	// 泛型里面的构造方法
	public FanXingDemoTwo() {
		this.setAge((T) new Integer(12));
		this.setName((V) "Amy");
	}

	public FanXingDemoTwo(T age, V name) {
		super();
		this.age = age;
		this.name = name;
	}

	public T getAge() {
		return age;
	}

	public void setAge(T age) {
		this.age = age;
	}

	public V getName() {
		return name;
	}

	public void setName(V name) {
		this.name = name;
	}

	public String toString() {
		return "FanXingDemoTwo [age=" + age + ", name=" + name + "]";
	}
	

}

package cn.suyuesheng.fanxing;

public class FanXingDemoTwoTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		FanXingDemoTwo<Integer, String> cc = new FanXingDemoTwo<Integer, String>();
		cc.setAge(12);
		cc.setName("hah");
		System.out.println(cc.toString());
		System.out.println(">=================");
		FanXingDemoTwo<Integer, String> bb = new FanXingDemoTwo<Integer, String>(20, "JJK");
		System.out.println(bb.toString());
		System.out.println(new FanXingDemoTwo<Integer, String>(40, "lili"));
		System.out.println(cc);
		System.out.println(">================");
		fun(cc);
		fun(new FanXingDemoTwo<Number, String>(120, "kkl"));
	}

	// 泛型的上限和下限
	/* 泛型的上限和下限
	 * extends 定义上限
	 * super 定义下限
	 * ?表示全部类型(任意类型)
	 * */
	public static void fun(FanXingDemoTwo<? extends Number, ? super String> temp) {
		
		System.out.println(temp.getName());
		System.out.println(temp);
		
	}
	public static void hun(FanXingDemoTwo temp) {
		temp.setAge("qqq");//这是错误的
		//错误的原因是:实例化对象设定的age的数据类型是Int。hun方法里却改数据类型为String。
		
	}

}

泛型的接口👇

package cn.suyuesheng.fanxing;
//泛型接口

interface Imessage<T>{
	void print(T t);
}
class Message<T> implements Imessage<T>{//这种定义方法把泛型类型也给继承了了
	public void print(T t) {
		System.out.println(t);
	}
}
class Lmessage implements Imessage<Integer>{//这种方式在继承的同时注明了接口泛型的类型
	public void print(Integer t) {//这里参数类型必须是Integer
		System.out.println(t);
	}
}
public class FanXingInterface {
	public static void main(String[] args) {
		Imessage<String> cc = new Message<String>();
		cc.print("hello");
		Imessage<Integer> bb = new Lmessage();
		bb.print(12);
	}
}

枚举

枚举可以限制一个类对象产生的范围

package cn.suyuesheng.meijv;

//枚举
//枚举实现接口
interface IColor{
	public abstract void jj();
}
enum Color implements IColor{
	RED("red"){
		public void fun() {
			System.out.println("红色");//每一个枚举对象都要覆写抽象方法
		}
		public void jj() {//每一个枚举对象都要覆写实现的接口的抽象方法
			System.out.println("枚举能不用就不用");
		}
	},GREEN("green"){
		public void fun() {
			System.out.println("绿色");
		}
		public void jj() {
			System.out.println("每一个枚举对象都要覆写实现的接口的抽象方法");
		}
	},BLUE("blue"){
		public void fun() {
			System.out.println("蓝色");
		}
		public void jj() {
			System.out.println("每一个枚举对象都要覆写实现的接口的抽象方法");
		}
	};
	//枚举中为对象的属性赋值
	private Color(String name){//构造方法必须private
		System.out.println("001");//会被执行三遍
		this.setName(name);
	}
	private String name;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	//枚举中的抽象方法
	public abstract void fun();
}

public class MeiJvDemoOne {
	public static void main(String[] args) {
		Color c = Color.BLUE;
		System.out.println(c);
		System.out.println(">==================");
		for (Color c1 : Color.values()) {
			System.out.println(c1);
			System.out.println(c1.ordinal());// 返回编号
			System.out.println(c1.name());// 返回数据
			System.out.println(c1.getName());
		}
		c.setName("hh");
		System.out.println(c.getName());
		Color.RED.fun();
		System.out.println(">++++++++++++++");
		for(Color b:Color.values()) {
			b.fun();
			b.jj();
			System.out.println(b.getName());
			System.out.println(b.name());
		}

	}
}

在这里插入图片描述

Annotation

//@Override 保证覆写的正确性
//@Override只能在方法上应用。在类和属性上是不能被用的。
//@Deprecated 声明不建议的或过期的类或方法
//Annotation
//@Override 保证覆写的正确性
//@SuppressWarnings 压制警告
package cn.suyuesheng.annotation;
//@Override 保证覆写的正确性
//@Override只能在方法上应用。在类和属性上是不能被用的。
//@Deprecated 声明不建议的或过期的类或方法
//Annotation
//@Override 保证覆写的正确性
//@SuppressWarnings 压制警告
class Book{
	@Override
	public String toString() {//这时,toString方法如果写成tostring的话,会在编译时就出错
		return "hello";
	}//@Override只能在方法上应用。在类和属性上是不能被用的。
	//@Deprecated 声明不建议的或过期的类或方法
	@Deprecated
	public void fun(String t) {
		System.out.println(t);
	}
	public void fun(int i,String t) {
		System.out.println(i+t);
	}
}
//@SuppressWarnings 压制警告
class Term<T>{
	private T age;
	public void setAge(T age) {
		this.age = age;
	}
	public T getAge() {
		return age;
	}
}
//@Deprecated可以声明类
@Deprecated
class Person{
	public void add() {
		System.out.println("过期");
	}
}
public class AnnotationDemoOne {
	@SuppressWarnings("unchecked")
	public static void main(String[] args) {
		System.out.println(new Book());//hello
		Book b =new Book();
		b.fun("hello");//这就是不建议的
		@SuppressWarnings({ "unused", "rawtypes" })
		Term t = new Term();//这样就没有警告了
		t.setAge(12);
		System.out.println(t.getAge());
	}
}

jdk1.8新特性

  • 接口可以定义普通方法,通过default和static
  • jdk 1.8新特性之Lambda,意义是简化匿名内部类的代码
package cn.suyuesheng.xintexing;
//jdk 1.8 新特性
//接口可以定义普通方法,通过default和static
interface IUsb{
	void message();
	default void fun() {
		System.out.println("default定义接口普通方法");
	}
	static void print() {
		System.out.println("static 定义静态方法");
	}
}
class Flash implements IUsb{

	@Override
	public void message() {
		// TODO Auto-generated method stub
		System.out.println("覆写");
		
	}
	
}
//jdk 1.8新特性之Lambda,意义是简化匿名内部类的代码
interface Ik{
	void ko();
//	void add(int i,int j);
}
interface Ib{
	void add(int i,int j);
}
public class XinTeXingDemo {
	public static void main(String[] args) {
		IUsb a = new Flash();
		a.fun();
		IUsb.print();
		a.message();
		/*
		 * default定义接口普通方法
		   static 定义静态方法
		      覆写*/
		funn(()->System.out.println("hello world"));
		ll((cv,b)->System.out.println(cv+b));
	}
	public static void funn(Ik ik) {
		ik.ko();
	}
	public static void ll(Ib ib) {
		ib.add(10, 20);
	}

}

  • jdk 1.8 方法引用
package cn.suyuesheng.xintexing;

//jdk 1.8 方法引用
/**
 * 
 * @author 苏月晟
 *
 * @param <P> 参数类型
 * @return <R> 返回值类型
 */
@FunctionalInterface // 此注解说明是函数式接口,只能定义一个方法
interface IMessage<P, R> {
	public R fun(P p);// 静态方法引用
}
/**
 * 
 * @author 苏月晟
 *
 * @return <R>
 */
@FunctionalInterface // 此注解说明是函数式接口,只能定义一个方法
interface IGod<R> {
	public R up();// 普通方法引用
}
/**
 * 特定类方法引用
 * @author 苏月晟
 *
 * @param <P>
 * @return <R>
 */
@FunctionalInterface
interface It<P,R>{
	public R eq(P p1,P p2);//特定类方法引用
}
/**
 * 构造方法引用
 * @author 苏月晟
 *
 * @return <R>
 */
@FunctionalInterface //确保函数式接口,只能定义一个方法
interface IG<R>{
	public R IG(int g2,String g1);//构造方法引用
}
class G{
	private int age;
	private String name;
	
	public G(int age, String name) {
		super();
		this.age = age;
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@Override
	public String toString() {
		return "G [age=" + age + ", name=" + name + "]";
	}
	
	
}
public class XinTeXingDemoTwo {
	public static void main(String[] args) {
		// 引用静态方法
		// 类名称 :: 静态方法名称
		// 将String.valueOf()的方法变为了IMessage接口里面的fun方法,也就是说msg里面的fun方法被覆写
		// 覆写内容是String.valueOf()的内容
		// 注意,Integer是String.valueOf()的参数类型
		// String是String.valueOf()的返回值类型
		// String.valueOf()是静态方法
		IMessage<Integer, String> msg = String::valueOf;
		System.out.println(msg.fun(12));// 12
		System.out.println(msg.fun(12) instanceof String);// true
		System.out.println(Integer.parseInt(msg.fun(10000).replaceAll("0", "9")));
		int cc = Integer.parseInt(msg.fun(10000).replaceAll("0", "9"));
		System.out.println(new Integer(cc) instanceof Integer);// true
		int df = 7;
		// 普通方法引用
		// 实例化对象 :: 普通方法名称
		IGod<String> igo = "hello"::toUpperCase;// 相当于igo的up方法是hello的toUpperCase方法
		System.out.println(igo.up());// HELLO
		System.out.println(igo.up() instanceof String);// true
		It<String,Boolean> it = String :: equalsIgnoreCase;
		System.out.println(it.eq("hello","kkk"));//引用的方法使用起来是,"hello".equalsIgnoreCase("kkk")
		//构造方法引用
		IG<G> gg = G::new; 
		System.out.println(gg.IG(12, "hello").toString());//G [age=12, name=hello]
	}
}

  • 内建函数式接口
    java.util.function中的类
package cn.suyuesheng.xintexing;

import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

//内建函数式接口,因为内建函数式接口的存在,我们很少直接定义函数式接口
/*函数式接口的种类
 * 静态  类::方法名称
 * 普通方法  实例化对象::方法名称
 * 特定类方法 类::方法名称
 * 构造方法 类::new
 * */
/*内建式函数接口的种类: 
 * Function apply 有返回值和参数
 * Consumer accept 有参数,没有返回值
 * Supplier get 有返回值,没有参数
 * Predicat test 有参数,返回值是Boolean
 * */
public class NeiJian {
	public static void main(String[] args) {
		Function<String, Boolean> ff = "ll"::equalsIgnoreCase;
		System.out.println(ff.apply("LL"));
		Consumer<String> cc = System.out::print;
		cc.accept("hello world");
		System.out.println("\n");
		Supplier<String> ss = "ll"::toUpperCase;
		System.out.println(ss.get());
		Predicate<String> pp = "lllhello"::contains;
		System.out.println(pp.test("a"));
	}
}

线程

一个java程序至少有两个线程,一个是main,一个是垃圾收集线程。
线程的实现有三种方法
第一种,👇 Thread。要使用Thread,必须要继承他,并实现run()方法。run()方法是线程的主体。要启动多线程,就必须要调用从Thread类中的start()方法
线程运行的过程中,交错运行,抢占cpu

package cn.suyuesheng.xiancheng.thread;
//多线程
class MyThread extends Thread{
	private String name;
	public MyThread(String name) {
		this.name=name;
	}
	public void run() {//run()是线程的主体
		for(int i=0;i<100;i++) {
			System.out.println(this.name+"\t"+i);
		}
	}
}
public class ThreadDemoOne {

	public static void main(String[] args) {
		MyThread a1 = new MyThread("001");
		MyThread a2 = new MyThread("002");
		MyThread a3 = new MyThread("003");
		a1.start();//启动多线程
		a2.start();//交错运行,抢占cpu
		a3.start();
		
	}

}

第二种,实现Runnable接口。实现Runnable可以避免单继承局限,并且能够共享数据资源。一般情况下,选择Runnable

package cn.suyuesheng.xiancheng.runnable;
//thread 是runnable的子类,使用runnable接口可以避免单继承局限,还能方便的实现数据共享

class Mthread implements Runnable{
	private int ticket =5;
	public void run() {
		for(int x:new int[100]) {
			if(ticket>0) {
				System.out.println(ticket--);
			}
		}
	}
}
public class RunnableDemo {
	public static void main(String[] args) {
		Mthread mm = new Mthread();
		new Thread(mm).start();
	}
}

Runnable和Thread 的关系?

Runnable是接口,Thread是类。且Thread是Runnable接口的子类。使用这两种方式都要覆写run()方法。run()方法为线程的主方法。

Callable。👇

 package cn.suyuesheng.xiancheng.callable;
//Callable 实现的子类里面call()方法可以有返回值

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

class MThread implements Callable<String>{
	public int ticket=10;
	public String call() throws Exception{
		for(int x:new int[100]) {
			if(ticket>0) {
				System.out.println(ticket--);
			}
		}
		return "票已经卖光";
	}
}
public class CallableDemo  {
	public static void main(String[] args) throws Exception{
		MThread mm = new MThread();
		FutureTask<String> mmm = new FutureTask<String>(mm);
		new Thread(mmm).start();//启动线程
		MThread bb = new MThread();
		FutureTask<String> bbb = new FutureTask<String>(mm);
		new Thread(bbb).start();//启动线程
		System.out.println(mmm.get());//获得线程返回的结果
		System.out.println(bbb.get());
	}
}

线程的相关方法
Thread.currentThread() 获得当前线程对象,有点像this
获得名字。Thread.currentThread().getName()
设置名字 setName 或在Thread构造方法中实现
优先级 setPriority 获得优先级 getPriority
睡眠和等待要try。。。catch
name.👇

 package cn.suyuesheng.xiancheng.fangfa;
class Mythread implements Runnable{
	private int ticket=100;
	public void run() {//线程方法
		for(int i=0;i<100;i++) {
			if(ticket>0) {
				System.out.println(Thread.currentThread().getName()+"\t"+ticket--);
				
			}
		}
	}
}
public class TestDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Mythread mm = new Mythread();
		new Thread(mm).start();
		new Thread(mm,"自定义命名A").start();
		new Thread(mm,"自定义命名B").start();
		new Thread(mm).start();
		new Thread(mm).start();
		mm.run();
	}

}

睡眠和优先级.👇

 package cn.suyuesheng.xiancheng.fangfa;

class Mth implements Runnable {

	public void run() {
		for (int i = 0; i < 100; i++) {
			try {
				Thread.sleep(1000);
				System.out.println(Thread.currentThread().getName() + "\t" + i);//Thread.currentThread()  获得当前线程对象,有点像this
			} catch (InterruptedException e) {
				// TODO: handle exception
				e.printStackTrace();
			}
		}
	}
}

public class SleepDemo {
	public static void main(String[] args) {
		Mth mm = new Mth();
		Thread bo = new Thread(mm,"hello");
		bo.setPriority(Thread.MAX_PRIORITY);//设定优先级
		bo.start();
		new Thread(mm, "A").start();
		new Thread(mm, "B").start();
		new Thread(mm, "C").start();
		//Thread.currentThread()  获得当前线程对象,有点像this
		System.out.println(Thread.currentThread().getPriority());//获得main对像的优先级
		
	}
}

 

同步 同步代码块 synchrenized(对象,一般是this){} 同步方法 public synchronized 返回值 方法名称(){} 同步,上锁,即使休眠,只要synchronized代码块没被运行完,就不会有其他的线程运行synchronized中的内容。 class Sale implements Runnable{ 同步。👇

 package cn.suyuesheng.xiancheng.fangfa;

//同步
//同步,上锁,即使休眠,只要synchronized代码块没被运行完,就不会有其他的线程运行synchronized中的内容
class Sale implements Runnable{
	private int foodBox = 100;
	public void run() {
		for(int i=0;i<35;i++) {
			try {
				Thread.sleep(100);
			}catch (InterruptedException e) {
				// TODO: handle exception
				e.printStackTrace();
			}
			synchronized (this) {//同步,上锁,即使休眠,只要synchronized代码块没被运行完,就不会有其他的线程运行synchronized中的内容
				if(foodBox>0) {
					try {
						Thread.sleep(100);
					}catch (InterruptedException e) {
						// TODO: handle exception
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName()+"\t"+foodBox--);
				}
			}
		}
	}
}
//synchronized 方法
class SaleOther implements Runnable{
	private int cup =20;
	public void run(){
		for(int i=0;i<20;i++) {
			try {
				Thread.sleep(10);
			}catch (InterruptedException e) {
				// TODO: handle exception
				e.printStackTrace();
			}
			this.buy();
		}
	}
	public synchronized void buy() {
		if(cup>0) {
			try {
				Thread.sleep(100);
			}catch (InterruptedException e) {
				// TODO: handle exception
				e.printStackTrace();
			}
			System.out.println("恭喜"+Thread.currentThread().getName()+"! "+"买到了最后\t"+cup--+" 个");
		}
	}
}
public class TongBu {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
//		Sale m = new Sale();
//		new Thread(m,"A").start();
//		new Thread(m,"B").start();
//		new Thread(m,"C").start();
		SaleOther bb = new SaleOther();
		Thread co = new Thread(bb,"D1");
		co.setPriority(Thread.MAX_PRIORITY);
		co.start();
		new Thread(bb,"A1").start();
		new Thread(bb,"B1").start();
		new Thread(bb,"C1").start();
		System.out.println(">____________");
		System.out.println(Thread.currentThread().getPriority());
		
	}

}

posted @ 2020-01-31 17:10  sogeisetsu  阅读(511)  评论(0编辑  收藏  举报