Java基础

ArrayList

  • 线程不安全
  • 底层是数组 实现的, 无参定长10,空间不够1.5倍扩容,指定一个int值,以这个值为基础扩容

Vector

  • 线程安全 sycnchroniszed
  • 底层也是数组
  • 扩容不指定默认2倍

LinkList

  • 线程不安全
  • 底层是双向链表和双端队列

HashSet

  • 不错存放重复的元素 实现了接口Set都一个样
  • 接口对象存放数据是无序的
  • 底层是链表+数组+红黑树
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import java.util.HashSet;
import java.util.Objects;

public class Demo10 {
public static void main(String[] args) {
HashSet test = new HashSet();
test.add(new Student("A", 123));
test.add(new Student("A", 123));
test.add(new Student("B", 123));
System.out.println(test);
}
}
class Student{
String name;
int age;

public Student(String name, int age) {
this.name = name;
this.age = age;
}



@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && name.equals(student.name);
}

@Override
public int hashCode() {
return Objects.hash(name, age);
}

@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
  • 主要理解下底层结构,n个链表,链表头用数组存储,数组每个元素都是一个链表的表头

    每次添加元素先计算HashCode() 看看属于哪一个链表,然后在相应的表头中按尾插法插入链表,如果存在相同的HashCode会使用equals方法 比较其元素是否相等,相等则不加入!!

  • 因此如果这个规则是可以自己重写的,按照自己的想法是否判断他们相等-》重写HashCode 和equals方法即可

泛型编程

  • 参数化类型 JDK5.0出现的新特性

多线程

  • 一个普通程序和并发程序区别

image-20221128091731127

Process 与 Thread

  • Process 进程,是一个程序执行的过程(静态概念),是系统资源分配的单位
  • 一个进程中可以包含若干个线程,一个进程至少有一个线程,线程是cpu调度和执行的单位。
  • 线程是独立执行的路径
  • 运行一个简单程序,即使自己没有创建线程,后台也会有主线程,gc线程(垃圾回收线程,守护线程)
  • main()称为主线程
  • 同一份资源操作时,会存在资源抢夺问题,需要加入并发控制
  • 线程调度是cpu,不能人为干预先后,线程会带来额外的开销
  • 每个线程在自己的工资内存中交换,内存控制不当会造成数据不一致

Thread Runnable Callable

  • Thread类

继承Thread

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Demo11 extends Thread{
//继承Thread 多线程 父类
@Override
public void run() {
//run方法线程体
for (int i = 0; i < 20; i++) {
System.out.println("---------------------这是一个偷跑的线程" + i);
}
}


public static void main(String[] args) {

//调用start开启线程
Demo11 demo11 = new Demo11();
demo11.start();


for (int i = 0; i < 300; i++) {
System.out.println("主线程" + i);
}
}
}

image-20221128094114507

交替执行这个输入语句,先后顺序看无法决定

  • 实现Runnable接口

这是一个接口!Thread是实现的这个接口 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class Demo12 {
public static void main(String[] args) {
//Thread 继承
new Test1().start();//使用Thread 继承 实现多线程

//Runnable 接口实现
//推荐使用 毕竟java单继承 多实现
new Thread(new Test()).start();//使用Runnable接口 重写run方法 然后再放入Thread 实现类中运行
}
}

class Test implements Runnable{
@Override
public void run() {
while(true){
System.out.println("黄牛正在抢Iphone");
}
}
}

class Test1 extends Thread{
@Override
public void run() {
while(true){
System.out.println("黄牛正在倒卖");
}
}
}
  • 线程不安全
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class Demo13 {
public static void main(String[] args) {
new Thread(new Tickes(), "小明").start();
new Thread(new Tickes(), "张三").start();
new Thread(new Tickes(), "李四").start();

}
}

class Tickes implements Runnable{
private int tick = 10;
@Override
public void run() {
while(true) {
if (tick == 0)
return;
System.out.println(Thread.currentThread().getName() + "抢到了第" + tick-- + "张票");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}

image-20221128102946627

同一份资源反复被多个人获取

  • 一个龟兔赛跑简单的多线程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
public class Demo14 {//龟兔赛跑

public static void main(String[] args) {
new Thread(new Rabbit(10, 200), "兔子").start();
new Thread(new Tortoise(2, 200), "乌龟").start();

}
}


class Rabbit implements Runnable{
int speed;//速度
int distance;
@Override
public void run() {
while(true){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
distance -= speed;
System.out.println("兔子正在跑步");
if (distance <= 0)
break;
if ((int)(Math.random() * 10 % 2) == 1) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("兔子睡觉了");
}

}
System.out.println("兔子跑完了");
}

public Rabbit(int speed, int distance){
this.speed = speed;
this.distance = distance;
}

}

class Tortoise implements Runnable{
int speed;//速度
int distance;
@Override
public void run() {
while(true){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
distance -= speed;
System.out.println("乌龟正在跑步");
if (distance <= 0)
break;


}
System.out.println("乌龟跑完了");
}

public Tortoise(int speed, int distance){
this.speed = speed;
this.distance = distance;

}

}
  • Callabe 接口 实现简单多线程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import javax.xml.namespace.QName;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Demo15 {
public static void main(String[] args) {
//创建执行服务器 分配线性池 3个
ExecutorService es1 = Executors.newFixedThreadPool(3);

//添加三个线程 会有返回值
es1.submit(new DownLoadMusic("音乐1"));
es1.submit(new DownLoadMusic("音乐2"));
es1.submit(new DownLoadMusic("音乐3"));

//关闭服务
es1.shutdownNow();

}
}

class DownLoadMusic implements Callable<Boolean> {
String name;
DownLoadMusic(String name){
this.name = name;
}

@Override//Callable执行体
public Boolean call() throws Exception {

System.out.println("正在下载"+ name);
Thread.sleep(1000);
return true;
}

}