javase基础学习
JAVA基础语法
基础语法
位运算
& | ^ ~ << >>
流程控制学习
Scanner
Scanner scanner = new Scanner(System.in);
String str = scanner.next();//输入时遇到空格结束
String str=scanner.nextlLine();//输入时enter结束
判断输入是否正确
if(scanner.hasNextInt()){输入}`
`else error;
判断是不是输入整型
增强for循环
int [][] m = {{1,2,3,4,5},{1,2,3,4,5}};
for(int[] x:m)
for(int y:x)
System.out.println(y);
方法详解
方法定义
方法重载
方法名字一样 参数列表(必须)不同和返回类型不同
public int max(int a,int b)
{
}
public double max(double a ,double b)
{
}
可变参数
public static void test(int ...i){
System.out.println(i[0]);
}
main(){
test(1,2,3,4);
}
递归
阶乘
public static int f(int n)
{
• if(n==1) return 1;
else return n*f(n-1);
}
数组
数组声明和创建
int[] num1;//
num = new int[10];
数组初始化
1.动态初始化(包含默认初始化)
int[] num1;
num = new int[10];
num[0]=1;//剩下的数组默认为0(即为默认初始化)
2.静态初始化
int[] num ={1,2,3,4,5};
数组使用
数组反转
public static int[] reverse(int [] m)
{
int[] res = new int[m.length];
for(int i=0,j=m.length-1;i<m.length;i++,j--)
{
res[i] = m[j];
}
return res;
}
二维数组
int
Arrays类
import java.util.Arrays
int[] a={1,2,3,45,6,7},
System.out.println(Arrays.toString(a));//打印数组元素
//打印结果[1, 2, 3, 45, 6, 7]
//数组排序 void类型
Arrays.sort(b);
for(int x: b)
System.out.print(x);
冒泡排序
boolean用来判断数组是不是已经排序好了 避免多有的排序
boolean flag=false;
for (int i= 0; i < a.length -1;i++)
{
for(int j=0;j<a.length-i-1 ;j++)
{
if(a[j+1]<a[j])
{
int term = a[j];
a[j]= a[j+1];
a[j+1] = term;
flag = true;
}
}
if(flag==false) break;
}
稀疏数组
代码见demo5
面向对象
概念
本质:
以类的方式组织代码,以对象的组织(封装)数据
特性:
继承、封装、多态
静态和非静态方法的区别
静态:
public class Student{
public static void say();//静态
public void say();//非静态
}
public static void main(String[] args)
{
静态调用:
Student.say();
//非静态调用
Student student = new Student;
student.say();
}
静态方达不能调用非静态方达
值传递和引用传递
//值传递和引用传递
public class demo01 {
public static void main(String[] args) {
int a = 0;
turn(a);
System.out.println(a);//值传递a的值不变
Person person = new Person();
System.out.println(person.name);//输出是空
change(person);
System.out.println(person.name);输出“123";
}
public static void turn(int c ){
c = 10;
}
public static void change(Person person)
{
person.name = "123";
}
public static class Person{
String name;//null
}
}
类和对象的创建
创建和初始化对象
new
构造器
和类名相同 没有返回值
class Person()
{
}
一个类会自动隐士构造一个无参构造 如果想使用有参构造 就必须显示定义无参构造
一个类即使什么都不写也会存在一个构造方法
//一个类即使什么都不写也会存在一个方法
//无参构造器
//1.使用new关键字本质在调用构造器
//2.用于初始化值
public Person(){
}
//有参构造器
public Person(String name)
{
this.name = name;
}
封装详解
封装的概念
封装:数据的隐藏
程序追求 高内聚低耦合
inde快捷键 ALT + INS
继承
extends
Super详解
方法重写
多态
动态编译
动态是方法的多态
Person s1 = new Student();
对象能执行哪写方法看左边类型 和右边关系不大
1.多态是方法的多态 不是属性的多态
2.父类和子类 有联系
3,存在条件 继承关系 子类需要重写 父类的引用指向子类对象
static、final 、private方法不能重写
Static 关键字
抽象类
关键字abstract
抽象类的所有方法必须要继承的子类实现 除非子类也是abstract
特点:
1.不能用来new 只能靠子类实现
2.抽象类 里面可以写普通方法 抽象方法必须在抽象类里面
接口的定义与实现
关键词 interface
实现接口: implements
demo09jiekou
内部类
异常处理
Exception
捕获和抛出异常
关键字:try catch finally throw throws
抛出异常快捷键:
cTRL +ALT+ T
try {
System.out.println(b/a);
} catch (Exception e) {
e.printStackTrace();//打印错误栈信息
}
//throw 和 throws 的区别
自定义异常
集合框架详解
基本概念
集合:对象的容器,实现对多个对象进行操作的常用方法
与数组区别:
1.长度不固定
2.数组可以储存基本类型和引用类型 集合只能储存引用类型
位置:java.util.*
Collection体系集合
Collection 使用
方法:
Collection collection = new ArrayList();//Arraylist 有顺序的
//添加元素
collection.add("苹果");
collection.add("香蕉");
collection.add("橘子");
System.out.println(collection.size());
System.out.println(collection);
输出结果
删除操作:
collection.remove("香蕉");
System.out.println(collection);
清空:
collection.clear();
遍历元素
方法1:增强for
for (Object object: collection) {
System.out.println(object);
}
方法2:迭代器
Iterator
//迭代过程不能使用collection改变元素
Iterator it = collection.iterator();
while(it.hasNext())
{
String s = (String)it.next();
System.out.println(s);
}
判断
1.判断元素是否存在
System.out.println(collection.contains("苹果"));
输出true
collection与对象 的使用
//新建collection 对象
Collection collection = new ArrayList();
Student s1 = new Student("张三",11);
Student s2 = new Student("里斯",12);
Student s3 = new Student("王五",13);
//1.添加数据
collection.add(s1);
collection.add(s2);
collection.add(s3);
System.out.println(collection.size());
System.out.println(collection.toString());
//2.删除
collection.remove(s1);
//3.清除
//collection.clear();
//4.遍历
List
特点: 有序 有下标 元素可以重复
方法:
使用方法
/创建集合
List list =new ArrayList<>();
//添加元素
list.add("小米");
list.add("华为");
list.add("oppo");
System.out.println(list.size());
//2.删除元素
// list.remove("oppo");
// list.remove(0);
//3.遍历
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
//增强for
for (Object o : list) {
System.out.println(o);
}
System.out.println("++++++++");
//迭代器
Iterator it = list.iterator();
while(it.hasNext())
System.out.println(it.next());
System.out.println("___________________列表迭代器从前往后");
//列表迭代器 允许按照任一方向遍历 还可以添加删除修改
ListIterator it0 =list.listIterator();
while(it0.hasNext())
{
System.out.println(it0.nextIndex()+":"+it0.next());
}
//"从后往前"
System.out.println("___________________列表迭代器从h后往前");
while(it0.hasPrevious())
{
System.out.println(it0.previousIndex()+":"+it0.previous());
}
//4.判断是否存在 是否为空
System.out.println(list.contains("小莫"));
System.out.println(list.empty());
//获取元素位置
System.out.println(list.indexof("华为") );
}
list将对象存入之后如何调对象的值
((Student)list.get(i)).getname();
student对象是student类型 而list对象是Object类型 所有需要强制类型转换
list中数据的比较:
lsit.get(i).equals(list.get(j));
list的实现类:
1.Arraylist
数组 查找 遍历速度快 增加删除速度慢
//1.增加元素
Student s1= new Student("杨哥",20);
Student s2= new Student("帅哥",20);
Student s3= new Student("阳哥",20);
Student s4= new Student("老哥",20);
arraylist.add(s1);
arraylist.add(s2);
arraylist.add(s3);
System.out.println("元素个数"+arraylist.size());
//2.删除元素
// arraylist.remove(s1);
// System.out.println("删除之后元素个数"+arraylist.size());
//arraylist.remove(new Student("帅哥",20));!!!重写了Student中的equals函数
// System.out.println("删除之后元素个数"+arraylist.size());
//3.遍历元素【红重点】
for (Object o:arraylist) {
System.out.println(o.toString());
}
//3.1使用迭代器
Iterator it = arraylist.iterator();
while(it.hasNext())
{
Student s =(Student)it.next();
System.out.println(s.toString());
}
//3.2列表迭代器
//同list
//4.判断
System.out.println(arraylist.contains(s1));
System.out.println(arraylist.isEmpty());
//5.查找
System.out.println(arraylist.indexOf(s1));
}
}
2.vector
3.linklist
泛型
语法<T,....> T为类型占位符,表示一种引用类型
泛型类
public class MyGenerics<T>{
//使用泛型
//1.创建变量
T t;//不能new T
//2.添加方法
public void show(T t){
System.out.println(t);
}
//3.泛型作为方法返回值
public T get(){
return t;
}
}
public class testGenerics {
public static void main(String[] args) {
//使用泛型类创建对象
MyGenerics<String> mygenerics= new MyGenerics<>();
mygenerics.t="hello";
mygenerics.show("大家好");
String string = mygenerics.get();
System.out.println(string);
MyGenerics<Integer> mygenerics2 = new MyGenerics<>();
mygenerics2.t=2;
Integer in = mygenerics2.get();
mygenerics2.show(200);
System.out.println(in);
}
}
泛型接口
public interface MyInterface<T>{
String name = "张三";
T serve(T t);
}
class MyInterfaceImpl implements MyInterface<String>{
@Override
public String serve(String s) {
System.out.println(s);
return s;
}
}
泛型方法
public class GenericsMethod {
public <T> T show(T t)
{
T t2;
return t;
}
}
//泛型方法
GenericsMethod genericsMethod = new GenericsMethod();
genericsMethod.show(" ");
genericsMethod.show(200);//由传递的数据决定类型
genericsMethod.show(3.14);
泛型的好处
提高代码的重用性
防止类型转换异常 提高代码的安全性
泛型集合
ArrayList <Student> arrayList2 = new ArrayList<Student>();
Student s1= new Student("name",20);
Student s2= new Student("name2",20);
arrayList2.add(s1);
arrayList2.add(s2);
for(Student s : arrayList2)
System.out.println(s);
System.out.println(s1.getName());
set集合
特点:元素不可重复 无序无下标
方法:全部继承自Collection中的方法
接口
ublic static void main(String[] args) {
Set<String> set = new HashSet<>();
//1.添加
set.add("苹果");
set.add("香蕉");
set.add("橘子");
System.out.println(set.size());
set.add("橘子");
System.out.println(set.size());//添加相同元素后没有加进去
//2.删除
set.remove("橘子");
System.out.println("删除后元素个数"+set.size());//添加相同元素后没有加进去
//3.遍历
//3.1 z增强for
System.out.println("---------------------增强for输出");
for (String s:set) {
System.out.println(s);
}
//3.2迭代器
System.out.println("---------------------迭代器输出");
Iterator<String> it = set.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
//4.判断
//是否为空
System.out.println(set.isEmpty());
//判断元素
System.out.println(set.contains("苹果"));
HashSet 【重点】
存储方式:哈希表
存储过程:
(1)根据hashcode计算保存位置,如果位置为空则直接报存不为空则执行第二部
(2)再执行equals方法:如果equals为true,则认为是重复,否则形成链表
Person p1 = new Person("老王",25);
Person p2= new Person("老李",28);
Person p3 = new Person("老张",23);
HashSet<Person> hashset2 = new HashSet<Person>();
hashset2.add(p1);
hashset2.add(p2);
hashset2.add(p3);
System.out.println(hashset2);//可以看到 与顺序无关
hashset2.add(new Person("老王",25));//需要重写HashCode和equals才能判断是重复的 重写之前加进去了 重写之后就加不进去了
Person对象重写:
@Override
public int hashCode()
{
int n1=this.name.hashCode();
int n2=this.age;
return n1+n2;
}
@Override
public boolean equals(Object obj) {
if(this == obj) return true;
if(obj==null) return false;
if(obj instanceof Person)
{
Person p =(Person) obj;
if(this.name.equals(p.getName())&&this.age==p.getAge())
{
return true;
}
}
return false;
}
hashcode 中的31的作用
(1)31是质数 减少散列冲突
(2)31提高执行 效率 是(i<<5) -i 左移五位
TreeSet
基于排序 实现元素不重复
实现了SortedSet接口,对集合元素自行排序
元素对象的类型必须实现Comparable接口 ,指定排序规则
通过CompareTo方法确定是否为重复元素
实现接口Comparable
Comparable接口
@Override
public int compareTo(Person o) {
int n1 = this.getName().compareTo(o.getName());
int n2 = this.age - o.getAge();
return n1==0?n2:n1;//x先比姓名再比年龄
}
comparator接口
另外定义比较规则
/*
*实现案例 通过treeSet方法按照字符串长度比较字符串
*/
public class demo02 {
public static void main(String[] args) {
TreeSet<String> tree =new TreeSet<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
int n1=o1.length()-o2.length();
int n2=o1.compareTo(o2);
return n1==0? n2:n1;
}
});
tree.add("sada");
tree.add("sdadasda");
tree.add("sdada");
tree.add("dasdadasda");
tree.add("dsada");
System.out.println(tree);
}
}
Map集合
Map接口特点:
1.用于存储任意键值对(Key-value)
2.键:无序、无下标、不允许重复
3.值:无序、无下标、允许重复
Map父接口:
特点:存储一对数据(Key-Value)
方法:
V put(K key , V value)//将对象存入到集合中,关联键值,key重复则覆盖原值
Object get(Object key)//根据键获取对应的值
KeySet<K>//返回所有的key
Collectoon<V> values()//返回包含所有值的Collection集合
Set<Map,Entry<K,V>>//键值匹配Set集合
接口使用
//创建MAp集合
Map<String,String> map =new HashMap<>() ;
//添加元素
map.put("uk","英国");
map.put("USA","美国");
map.put("CHN","中国");
//删除
map.remove("uk");//删除的时候删键值就行
System.out.println("元素个数"+ map.size());
System.out.println(map.toString());
//遍历
//3.1使用KeySet
System.out.println("使用KeySet遍历————————————————————");
//Set<String > keyset = map.keySet();
for(String key:map.keySet())
{
System.out.println(key+" "+map.get(key));//map.get(key)获取值
}
//3.2使用entrySet方法 效率比KeySet高
//Set<Map.Entry<String,String>> entries= map.entrySet();
for(Map.Entry<String,String> entry : map.entrySet())
{
System.out.println(entry.getKey()+" "+entry.getValue());
}
//4.判断
System.out.println(map.containsKey("CHN"));
System.out.println(map.containsValue("中国"));
Map集合的实现类:
HashMap[重点]
线程不安全 运行效率快;允许使用null作为key或是value
HashTable
TreeMap
可以对key自动排序
存储结构:红黑树
重写Comparable
public class Person implements Comparable<Person>
@Override
public int compareTo(Person o) {
int n1=this.name.compareTo(o.getName());
return n1;
Collection工具类
方法:
重要!!!
//sort排序
Collections.sort(list);
System.out.println(list);
//二分查找
int i = Collections.binarySearch(list,16);//返回小标
System.out.println(i);
//copy
List<Integer> list2 = new ArrayList<>();
for (int k = 0; k < list.size(); k++) {
list2.add(0);
}
Collections.copy(list2,list);//必须要集合大小一样才行
System.out.println(list2);
//reverse 反转
Collections.reverse(list2);
System.out.println(list2);
//shuffle 打乱
Collections.shuffle(list2);
System.out.println(list2);
//list转数组 和数组转list
Integer[] a = list.toArray(new Integer[0]);
System.out.println(a.length);
System.out.println(Arrays.toString(a));//直接输出数组
//数组变集合
String[] name={"张三","里斯哦","saa"};
List<String > name2 = Arrays.asList(name);
//这个集合是个受限集合 不能删除添加 长度是固定的
int[]b ={1,2,3,4};
List<int []> list3 = Arrays.asList(b);
}
集合总结
IO流(还没总结)
JavaFX(还没总结)
按钮事件:
.setOnMouseClicked(new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {});
list.get(i) 获取第i个元素 但是是object类型
多线程详解
1.线程简介:
多线程
操作系统中运行的程序为进程,一个进程可以有多个线程
Process 进程 Thread线程
程序:
进程:
线程:
2.线程创建
Thread (class) 继承Thread类(重点)
Runnable(接口) 实现Runnable接口(重点)
Callable 实现Callable接口(了解)
Thread
不建议使用 避免OOP单继承局限性
自定义线程继承Thread
重写run方法 编写线程执行体
创建线程对象调用start方法
/*
*自定义线程继承Thread 重写run方法 编写线程执行体
*创建线程对象调用start方法开启线程
* 总结:线程开启不一定立即执行 由cpu调度
*/
public class TestThread extends Thread {
public void run()
{
for (int i = 0; i < 200; i++) {
System.out.println("我在看代码"+i);
}
//run方法线程体
}
public static void main(String[] args) {
//mian线程 主线程
//创建一个线程对象
TestThread testthread = new TestThread();
//调用start()方法开启
testthread.start();
//
for (int i = 0; i < 1000; i++) {
System.out.println("我在学习多线程"+ i);
}
}
}
Runnable
推荐使用 灵活方便 方便同一个对象被多个线程使用
!!!
TestThread3 testthread3 = new TestThread3();
//创建线程对象通过线程对象开启线程
new Thread(testthread3).start();
实现Runnable方法 执行线程需要丢入Runnable接口实现类 重写run方法
public class TestThread3 implements Runnable{
@Override
public void run()
{
for (int i = 0; i < 200; i++) {
System.out.println("我在看代码"+i);
}
//run方法线程体
}
public static void main(String[] args) {
//创建一个线程对象
TestThread3 testthread3 = new TestThread3();
//创建线程对象通过线程对象开启线程
new Thread(testthread3).start();
for (int i = 0; i < 1000; i++) {
System.out.println("我在学习多线程"+ i);
}
}
lambda表达式:
new Thread(()->sout("我爱你")).strat;
Caliable接口
了解即可
3.初识并发问题
买火车票案例
/*
*多线线程同时操作同一个对象
*买火车票的例子
* 发现问题:多个线程操作同一个资源时 出现资源紊乱
*/
public class TestThread4 implements Runnable {
//
private int ticketNum = 10;
@Override
public void run() {
while(true)
{
if(ticketNum<=0)
{break;}
//模拟延时
try{
Thread.sleep(200);
}catch(InterruptedException e)
{
e.printStackTrace();
}
System.out.println( Thread.currentThread().getName()+ "拿到了第"+ticketNum--+"张票");
}
}
public static void main(String[] args) {
TestThread4 ticks = new TestThread4();
new Thread(ticks,"小明").start();
new Thread(ticks,"老师").start();
new Thread(ticks,"黄牛").start();
}
}
输出:(同时出现了7)
老师拿到了第9张票 小明拿到了第8张票 黄牛拿到了第10张票 小明拿到了第7张票 老师拿到了第7张票 黄牛拿到了第6张票 老师拿到了第5张票 黄牛拿到了第4张票 小明拿到了第3张票 老师拿到了第2张票 黄牛拿到了第1张票 小明拿到了第0张票
Process finished with exit code 0
龟兔赛跑案例
/*
*模拟归龟兔赛跑
*/
public class Race implements Runnable {
private static String winnner;
public void run()
{
for (int i = 0; i <= 100; i++) {
//模拟兔子休息
if(Thread.currentThread().getName().equals("兔子")&&i%10==0)
{
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//判断比赛是否结束
boolean flag = gameover(i);
if(flag){
break;
}
System.out.println(Thread.currentThread().getName()+"跑了"+i+"步");
}
}
private boolean gameover( int steps)
{
if(winnner!=null) return true;
if(steps>=100){
winnner = Thread.currentThread().getName();
System.out.println("Winner is" + winnner);
return true;
}
return false;
}
public static void main(String[] args) {
Race race =new Race();
new Thread(race,"兔子").start();
new Thread(race,"乌龟").start();
}
}
4.静态代理
/*
*
* 静态代理模式
* 真实对象和代理对象都要实现同一个接口
* 代理对象必须代理真实对象
*
*/
public class StaticProxy {
public static void main(String[] args) {
WeddingCompany weddingCompany = new WeddingCompany( new You());
weddingCompany.happymarry();
}
}
interface Marry{
void happymarry();
}
//真是角色 你去结婚
class You implements Marry{
@Override
public void happymarry()
{
System.out.println("结婚了真开心");
}
}
//代理角色 帮助你结婚
class WeddingCompany implements Marry{
private Marry target;
public WeddingCompany(Marry target)
{
this.target = target;
}
@Override
public void happymarry()
{
before();
this.target.happymarry();
after();
}
public void before(){
System.out.println("结婚前 布置现场");
}
public void after()
{
System.out.println("结婚之后收尾款");
}
5.lambad表达式
因为Runnable只有一个run方法
interface TLike
{
void lambda();
}
psvm
//6.应lambda简化
tlike = () ->{
System.out.println("l like lambad5 lambda表达式");
};
tlike.lambda();
6.线程状态
创建状态
就绪状态
阻塞状态
运行状态
结束状态
线程方法:
停止线程
线程休眠
获取系统当前时间
while(true){
try {
Thread.sleep(1000);
Date StartTime = new Date(System.currentTimeMillis());//获取系统当前时间
System.out.println(new SimpleDateFormat("HH:mm:ss").format(StartTime));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
线程礼让yield
public class YieldTest {
public static void main(String[] args) {
MyYeild yt =new MyYeild();
new Thread(yt,"a").start();
new Thread(yt,"b").start();
}
}
class MyYeild implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"开始执行");
Thread.yield();
System.out.println(Thread.currentThread().getName()+"执行结束");
}
}
线程强行执行Join
public class JoinTest implements Runnable{
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("vip用户来了" +i);
}
}
public static void main(String[] args) throws InterruptedException {
JoinTest joinTest = new JoinTest();
Thread thread = new Thread(joinTest);
thread.start();
//主线程
for (int i = 0; i < 1000; i++) {
if(i==200) {
thread.join();//被插队
}
System.out.println("main"+i);
}
}
}
观测线程状态
/*
*观察线程状态
*
*/
public class StateTest {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(()-> {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("/////////");
});
//观察状态
Thread.State state = thread.getState();
System.out.println(state);
//观察启动后
thread.start();//启动线程
state = thread.getState();
System.out.println(state);//Run
while(state!=Thread.State.TERMINATED)
{
Thread.sleep(100);
state = thread.getState();
System.out.println(state);
}
}
}
线程优先级
public class PriorityTest {
public static void main(String[] args) {
//主线程默认优先级
System.out.println(Thread.currentThread().getName()+ "---> " + Thread.currentThread().getPriority());
MyPriority mypriorty = new MyPriority();
Thread t1 = new Thread(mypriorty);
Thread t2 = new Thread(mypriorty);
Thread t3 = new Thread(mypriorty);
Thread t4 = new Thread(mypriorty);
Thread t5 = new Thread(mypriorty);
//先设置优先级再启动
t1.start();
t2.setPriority(1);
t2.start();
t3.setPriority(4);
t3.start();
t4.setPriority(Thread.MAX_PRIORITY);//MAx.PRIORITY
t4.start();
t5.setPriority(8);
t5.start();
}
}
class MyPriority implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+ "---> " + Thread.currentThread().getPriority());
}
}
守护(deamon)线程
package JavaStudy.Thread.state;
/*
测试守护线程
当用户线程结束后 守护线程也停止了
*/
public class DaemonTest {
public static void main(String[] args) {
God god = new God();
You you = new You();
Thread thread =new Thread(god);
thread.setDaemon(true);//默认是false
thread.start();//上帝守护启动
new Thread(you).start();//线程 你启动
}
}
//
class God implements Runnable{
@Override
public void run() {
while (true)
{
System.out.println("上帝保佑你");
}
}
}
//你
class You implements Runnable{
@Override
public void run(){
for (int i = 0; i < 36500; i++) {
System.out.println("你一生都在开心得活着");
}
System.out.println("------doodbye");
}
}
7.线程同步机制
多个线程操作同一个资源
并发:
同一个对象被多个线程共同操作
线程同步
线程同步条件: 队列加锁
锁机制 synchronized
同步方法
银行取钱案例
//不安全的取钱
//两个人去银行取钱
//用synchronized同步块锁Account对象
public class USafeBank {
public static void main(String[] args) {
Account account = new Account(100,"结婚基金");
Drawing you = new Drawing(account,50,"你");
Drawing grilf = new Drawing(account,100,"妻子");
you.start();
grilf.start();
}
}
//账户
class Account {
int money;
String name;
public Account(int money, String name) {
this.money = money;
this.name = name;
}
}
//银行取款
class Drawing extends Thread{
Account account;//账户
//取了多少钱
int drawingMoney ;
//现在手里有多少钱
int NowMoney;
public Drawing(Account account,int drawingMoney,String name)
{
super(name);
this.account = account;
this.drawingMoney = drawingMoney;
}
//取钱
//synchornized默认锁的是this
@Override
public void run(){
//锁的对象是锁被更改的对象
synchronized (account)
{
//判断有没有钱
if(account.money - drawingMoney< 0)
{
System.out.println(Thread.currentThread().getName() + " 钱不够,取不了");
return;
}
//sleep放大问题发生
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//卡内余额 = 余额-你取的钱
account.money = account.money - drawingMoney;
//你手里的钱
NowMoney = NowMoney + drawingMoney;
System.out.println(account.name + "余额为: " +account.money);
System.out.println(this.getName()+ "手里的钱" + NowMoney);//this.getName() = Thread.currentThread().get name()
}
}
}
2.list案例
//线程不安全的集合
//线程可能添加到了同一个位置
public class UsafeList {
public static void main(String[] args) throws InterruptedException {
List<String> list = new ArrayList<String>();
for (int i = 0; i < 10000; i++) {
new Thread(()->{
synchronized(list) {
list.add(Thread.currentThread().getName());
}}).start();
}
Thread.sleep(3000);
System.out.println(list.size());
}
}
死锁
Lock锁
ReentranLock可重复锁
class TestLock2 implements Runnable{
int ticknum = 10;
//定义Locks锁
private final ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while(true)
{
try{
lock.lock();//加锁
if(ticknum>0)
{
System.out.println(Thread.currentThread().getName() + ticknum--);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else {
break;
}
}finally {
lock.unlock();//解锁
}
}
}
8.线程协作
生产者消费者问题
解决生产者消费者问题方法1:管程法
package JavaStudy.Thread.gaoji;
//生产者消费者模型 利用缓冲区解决:管程法
//生产者、消费者、缓冲区
public class TestPC {
public static void main(String[] args) {
SynContains container = new SynContains();
new Productor(container).start();
new Consunmer(container).start();
}
}
//生产者
class Productor extends Thread{
SynContains container;
public Productor(SynContains container){
this.container = container;
}
@Override
public void run(){
for (int i = 0; i < 100; i++) {
container.push(new Chicken(i));
System.out.println("生产了" + i+"只鸡 ");
}
}
}
//消费者
class Consunmer extends Thread{
SynContains container;
public Consunmer(SynContains container){
this.container = container;
}
public void run(){
for (int i = 0; i < 100; i++) {
System.out.println("消费了---->" + container.pop().id+"只鸡 ");
}
}
}
//产品
class Chicken{
int id;
public Chicken(int id) {
this.id = id;
}
}
//缓冲区
class SynContains{
//需要一个容器大小
Chicken[] chickens = new Chicken[10];
//容器计数器
int count = 0;
//生产者放入产品
public synchronized void push(Chicken chicken){
//如果容器满了 就等待消费者消费 没有满就丢入
if(count == chickens.length){
//通知消费者消费 生产等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果没有满 放入产品
chickens[count]=chicken;
count++;
//可以通知消费者消费
this.notify();
}
//消费者消费产品
public synchronized Chicken pop(){
//判断能否消费
if(count == 0)
{
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
//等待生产者生产,消费者等待
}
count--;
Chicken chicken = chickens[count];
//吃完了通知生产者生产
this.notify();
return chicken;
}
}
解决生产者消费者问题方法2:x信号灯法
package JavaStudy.Thread.gaoji;
//测试生产者消费者问题模型 : 信号灯法 通过标志位解决
public class TestPc2 {
public static void main(String[] args) {
TV tv =new TV();
new Player(tv).start();
new Watcher(tv).start();
}
}
//生产者--> 演员
class Player extends Thread{
TV tv;
public Player(TV tv){
this.tv=tv;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
if(i%2==0){
this.tv.play("快乐大本营播放中");
}
else {
this.tv.play("抖音记录美好生活");
}
}
}
}
//消费者:观众
class Watcher extends Thread{
TV tv;
public Watcher(TV tv){
this.tv=tv;}
@Override
public void run(){
for (int i = 0; i < 20; i++) {
tv.watch();
}
}
}
//产品 : 节目
class TV{
//演员表演的时候 观众等待
//观众看的时候 演员等待
String voice;
boolean flag = true;
//表演
public synchronized void play( String voice) {
if(!flag)
{
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("演员表演了" + voice);
//通知观众观看
this.notifyAll();
this.voice = voice;
this.flag = !this.flag;
}
//观看
public synchronized void watch(){
if(this.flag)
{
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("观众观看了" + voice);
//通知演员表演
this.notifyAll();
this.flag = !this.flag;
}
}
线程池
package JavaStudy.Thread.gaoji;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
//测试线程池
public class TestPool {
public static void main(String[] args) {
//1。创建线程池
ExecutorService sercive = Executors.newFixedThreadPool(10);
//newFixedThreadPool()参输为线程大小
sercive.execute(new MyThread());
sercive.execute(new MyThread());
sercive.execute(new MyThread());
//2.关闭
sercive.shutdown();
}
}
class MyThread implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
9.总结
网络编程(未总结)
GUI(未总结)
注解和反射
Annotation注解
注解入门
内置注解
@Override 重写
@Deprecated 不建议使用 有危险或者存在更好的使用
@SuppressWarnings
元注解
mate-Annotation
@Target
@Retention
自定义注解
@interface
package JavaStudy.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//自定义注解
public class demo03 {
@MyAnnotation2(name = " 阳",schools = {"西北大学,西工大"}) //注解可以显示赋值 如果没有默认值 必须赋值
public void test(){ }
@MyAnnotation3(" ")//只有一个注解时 可以直接赋值
public void test2(){ }
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
//注解的参数 : 参输类型 + 参输名 + ()
String name() default" ";//default ""默认成空
int age()default 0;
int id()default -1;//如果-1 代表不存在
String[] schools()default {"北大","清华"} ;//默认为清华北大
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation3{
String value();
}
Reflection反射机制
Java反射机制概述
优缺点;
优点:可以实现动态创建对象和编译,体现出很大的灵活性
缺点:对性能有影响 使用反射基本上是一种解释操作,这类操作慢于直接执行相同的操作
Class类
Class类常用方法
获取Class类的实例
package JavaStudy.Reflection;
import java.security.spec.RSAOtherPrimeInfo;
//测试class类的创建方式有哪些
public class test02 {
public static void main(String[] args) throws ClassNotFoundException {
Person person = new Student();
System.out.println("这个人是" + person.name);
//方式一:通过对象获得
Class c1 = person.getClass();
System.out.println(c1.hashCode());
//方式2forname获得
Class c2 = Class.forName("JavaStudy.Reflection.Student");
System.out.println(c2.hashCode());
//方式三 : 通过类名.class
Class c3 = Student.class;
System.out.println(c3.hashCode());
//方式四:基本内置类型的包装类都有一个type属性
Class c4= Integer.TYPE;//int 类
System.out.println(c4);
//获得父类类型
Class c5 = c1.getSuperclass();
System.out.println(c5);
}
}
class Person{
public String name;
public Person() {
}
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return super.toString();
}
}
class Student extends Person{
public Student(){
this.name = "学生";
}
}
class Teacher extends Person{
public Teacher(){
this.name = "老师";
}
}
所有类型的class
package JavaStudy.Reflection;
import java.lang.annotation.ElementType;
//所有类型的Class
public class Test03 {
public static void main(String[] args) {
Class c1 = Object.class;//类
Class c2 = Comparable.class;//接口
Class c3 = String[].class;//一维数组
Class c4 = int[][].class;//二维数组
Class c5 = Override.class;//注解
Class c6 = ElementType.class;//枚举类型
Class c7 = Integer.class;//基本类型
Class c8 = void.class;//void
Class c9 = Class.class;// Class
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
System.out.println(c4);
System.out.println(c5);
System.out.println(c6);
System.out.println(c7);
System.out.println(c8);
System.out.println(c9);
int a[] = new int[10];
int b[] = new int[5];
//只要元素类型与维度一样 class一样
System.out.println(a.getClass().hashCode());
System.out.println(b.getClass().hashCode());
}
}
分析类的加载器(还没有分析)
分析类初始化
//测试类的初始化
import java.sql.SQLOutput;
public class test04 {
static{
System.out.println("main类被加宰");
}
public static void main(String[] args) throws ClassNotFoundException {
//1.主动引用S
//Son son = new Son();
/*输出结果:
main类被加宰 父类被加宰 子类被加载 */
//2.反射引用
//Class.forName("JavaStudy.Reflection.Son");
/*输出结果:
main类被加宰 父类被加宰 子类被加载 */
//不会初始化的方法
//1.子类调用父类的静态方法
//System.out.println(Son.m);
//输出 main类加载 父类被加宰 0
//2。数组
Son[] son = new Son[5];//输出main类被调用 其他没有
//3.子类的静态常量
System.out.println(Son.M);//输出main类被调用 其他没有
}
}
class Father{
static{
System.out.println("父类被加宰");
}
static int m =0;
}
class Son extends Father{
static {
System.out.println("子类被加载");
}
}
类加载器(还未总结)
获取类的运行时结构
package JavaStudy.Reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.SQLOutput;
//获得类的信息
public class test05 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class c1 = Class.forName("JavaStudy.Reflection.User");
//获得类的名字
System.out.println(c1.getName()); //获得包名+类名
System.out.println(c1.getSimpleName()); //获得类名
//获得类的属性
System.out.println("====================");
Field[] fields = c1.getFields();//只能找到public类的属性
fields = c1.getDeclaredFields();//找到全部属性
for (Field field : fields) {
System.out.println(field);
}
//获得指定属性的值
Field name = c1.getDeclaredField("name");
System.out.println(name);
//获得类的方法
System.out.println("================方法");
Method[] methods = c1.getMethods();//获得public方法
for (Method method : methods) {
System.out.println(methods);
}
methods = c1.getDeclaredMethods();//获得全部方法
for (Method method : methods) {
System.out.println(methods);
}
//获得指定名字的方法
//需要方法的参输 和类型.class
Method getname = c1.getMethod("getName", null);
Method setName = c1.getMethod("setName", String.class);
System.out.println(getname);
System.out.println(setName);
//获得指定类的构造器
Constructor[] constructor = c1.getConstructors();
constructor = c1.getDeclaredConstructors();
for (Constructor constructor1 : constructor) {
System.out.println(constructor);
}
//获得指定的构造器
Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
System.out.println(declaredConstructor );
}
}
动态创建对象执行方法
调用方法:
USer user =(User)c1.newInstance();
c1.invoke(user,"setName");
调用属性
USer user =(User)c1.newInstance();
Field name=c1.getDeclaredField("name")//属性的名
name.set(user,"luyang");//如果是private类 在前面加 name.setAccessible(true);
性能对比分析
package JavaStudy.Reflection;
//性能对比分析
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class test07 {
//普通方式调用
public static void test1(){
User user = new User();
long start = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
user.getName();
}
long end = System.currentTimeMillis();
System.out.println("普通方法执行10亿次数"+(end-start)+"ms");
}
//反射方法调用
public static void test2() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException ,IllegalAccessException{
User user = new User();
Class c1= user.getClass();
Method getName = c1.getDeclaredMethod("getName", null);
long start = System.currentTimeMillis();
for (int i = 0; i <1000000000; i++) {
getName.invoke(user, null);
}
long end = System.currentTimeMillis();
System.out.println("反射方法执行10亿次数"+(end-start)+"ms");
}
////反射方法调用 关闭检测
public static void test3() throws ClassNotFoundException, NoSuchMethodException ,InvocationTargetException ,IllegalAccessException{
User user = new User();
Class c1= user.getClass();
Method getName = c1.getDeclaredMethod("getName", null);
getName.setAccessible(true);
long start = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
getName.invoke(user, null);
}
long end = System.currentTimeMillis();
System.out.println("关闭检测方法执行10亿次数"+(end-start)+"ms");
}
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException ,InvocationTargetException ,IllegalAccessException{
test1();
test2();
test3();
}
}
反射操作泛型(未总结)
获取注解信息
getAnnotations
getAnnotation
package JavaStudy.Reflection;
import java.lang.annotation.*;
import java.lang.reflect.Field;
//通过反射获取注解
public class test09 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
//通过反射获得注解
Class c1= Class.forName("JavaStudy.Reflection.Student2");
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
//获得注解的value值
luyang luyang = (luyang)c1.getAnnotation(luyang.class);
String value = luyang.value();
System.out.println(value);
//获得类的指定注解
Field name = c1.getDeclaredField("name");
Fieldyang annotation = name.getAnnotation(Fieldyang.class);
System.out.println(annotation);
}
}
@luyang("db-student")
class Student2{
@Fieldyang(columnName = "db-name",type = "String",length = 10)
private String name;
@Fieldyang(columnName = "db-id",type = "int",length = 10)
private int id;
@Fieldyang(columnName = "db-age",type = "int",length = 2)
private int age;
public Student2() {
}
public Student2(String name, int id, int age) {
this.name = name;
this.id = id;
this.age = age;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setId(int id) {
this.id = id;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "id:" + id
+"age:"+age+
"name:" +name;
}
}
//类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface luyang{
String value();
}
//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Fieldyang{
String columnName();//列名
String type();
int length();
}
JUC 并发编程
1.什么是JUC
java.util工具包、包、分类
业务:普通的线程代码 Thread
Runnable 没有返回值 效率相比Callable相对较低
2.传统的synchronized
package JavaStudy.JUC;
//传统的synchronized
public class demo01 {
public static void main(String[] args) {
tickets t =new tickets();
new Thread(()->{
for(int i =0;i<50;i++)
{
t.sole();
}
},"A").start();
new Thread(()->{
for(int i =0;i<50;i++)
{
t.sole();
}
},"B").start();
new Thread(()->{
for(int i =0;i<50;i++)
{
t.sole();
}
},"C").start();
}
}
class tickets{
int ticket =30;
public synchronized void sole(){
if(ticket>0)
System.out.println(Thread.currentThread().getName()+"抢到了第"+ticket+"张票 还剩下"+(30-ticket--));
}
}
3.Lock锁
公平锁: 先来后到
非公平锁: 可以插队(默认的)
package JavaStudy.JUC;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
//传统的synchronized
public class demo02lock {
public static void main(String[] args) {
tickets02 t = new tickets02();
new Thread(()->{ for(int i =0;i<50;i++) t.sole(); },"A").start();
new Thread(()->{ for(int i =0;i<50;i++) t.sole(); },"B").start();
new Thread(()->{ for(int i =0;i<50;i++) t.sole(); },"C").start();
}
}
//lock三部曲
//1.new ReentrantLock();
// lock.lock();加锁
//finally lock.unlock();解锁
class tickets02 {
int ticket = 30;
Lock lock = new ReentrantLock();
public void sole() {
lock.lock();//加锁
try {//放业务代码
if (ticket > 0)
System.out.println(Thread.currentThread().getName() + "抢到了第" + ticket + "张票 还剩下" + (30 - ticket--));
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();//解锁
}
}
}
lock和synchronized的区别
1.synchronized 是内置的关键字 lock是关键类
2.synchronized 无法判断获取锁的状态 lock可以判断是否获取了锁
3.synchronized 会自动释放锁子 lock如果不释放锁会 死锁
4.synchronized 线程一:(获得锁、阻塞) 线程二会一直等 但是lock不一定会等下去
5.synchronized 可重入锁 不可以中断 非公平锁 lock 可重入锁 可以判断锁,可以设置是否公平
6.synchronized 适合锁少量代码同步问题 lock 驶合锁大量的同步的代码
什么是锁
4.生产者消费者问题
面试常问: 1.单例模式 排序算法 生产者消费者问题 死锁
synchronized版
package JavaStudy.JUC;
public class demo03消费者问题 {
public static void main(String[] args) {
Date date = new Date();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
date.increament();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "A").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
date.decreament();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "B").start();
}
}
//资源类
//判断等待 业务 通知
class Date{
private int number = 0;
public synchronized void increament() throws InterruptedException {
if(number !=0) {
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName()+"----"+number);
this.notifyAll();
}
public synchronized void decreament() throws InterruptedException {
if(number==0)
{
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName()+"----"+number);
this.notifyAll();//通知其他线程 我减一完了
}
}
出现问题:ABCD四个线程时 出现虚假唤醒
解决方法: if改为 while方法
JUC 版生产者消费者
通过lock找到codition方法
代码实现“
package JavaStudy.JUC;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class demo04生产者Lock {
public static void main(String[] args) {
Date2 date = new Date2();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
date.increament();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "A").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
date.decreament();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "B").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
date.increament();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "C").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
date.decreament();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "D").start();
}
}
//资源类
//判断等待 业务 通知
class Date2{
private int number = 0;
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
public synchronized void increament() throws InterruptedException {
lock.lock();
try {
while(number !=0) {
condition.await();//等待
}
