总览
知识图解
总目录
第8章_多线程
程序、进程、线程
Java程序线程
何时需要多线程
run()、start()
创建线程
方式一:继承Thread类
方式二:实现Runnable接口
public class Test01 {
public static void main(String[] args) {
// 创建偶数输出线程
Thread evenThread = new Thread(new EvenNumberRunnable());
// 创建奇数输出线程
Thread oddThread = new Thread(new OddNumberRunnable());
// 启动线程
evenThread.start();
oddThread.start();
}
}
class EvenNumberRunnable implements Runnable {
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
if (i % 2 == 0) {
System.out.println("偶数:" + i);
}
}
}
}
class OddNumberRunnable implements Runnable {
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
if (i % 2 != 0) {
System.out.println("奇数:" + i);
}
}
}
}
Thread类——join()、yield()
join()
join()例子——轮流打印奇偶数
public class Test01 {
// 当前要打印的数字
private static int current = 1;
// 同步锁对象
private static final Object lock = new Object();
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
while (current <= 2) {
synchronized (lock) {
if (current % 2 == 0) {
System.out.println("线程 1:" + current);
current++;
} else {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
Thread thread2 = new Thread(() -> {
while (current <= 2) {
synchronized (lock) {
if (current % 2 != 0) {
System.out.println("线程 2:" + current);
current++;
} else {
lock.notify();
}
}
}
});
// 启动线程
thread1.start();
thread2.start();
// 等待线程执行完毕
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("最后:current = " + current);
}
}
线程的调度
线程的优先级
低优先级只是获得调度的概率低,并非一定是在高优先级线程之后才被调用,原因:
守护线程
线程——生命周期
线程的同步
异步问题
Synchronized
例1
public class Test01 {
public static void main(String args[]) throws InterruptedException {
Test01 synTest = new Test01();
synTest.test();
}
public void test() throws InterruptedException {
new SynThread1("abc").start();
//两个线程userName相同则可同步synchronized,否则是异步
new SynThread1("abc").start();
}
public void syn(String userName) throws Exception {
synchronized (userName) {
System.out.println("进入到同步块,userName=" + userName);
Thread.sleep(2000); //5秒
System.out.println("退出同步块,userName=" + userName);
}
}
class SynThread1 extends Thread {
String userName;
public SynThread1(String userName) {
this.userName = userName;
}
public void run() {
try {
syn(userName);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
例2
class Ticket implements Runnable {
private int tick = 10;
public synchronized void run() {
while (true) {
if (tick > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(Thread.currentThread
().getName() + "售出车票,tick号为:" +
tick--);
} else
break;
}
}
}
class Test01 {
public static void main(String[] args) {
Ticket t = new Ticket();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
t1.setName("t1窗口");
t2.setName("t2窗口");
t1.start();
t2.start();
}
}
解释:由于采用了同步synchronized,必须等t1执行完毕,但是执行完毕后tick已经为0,所以t2在if判断中就已经结束了
例3
多线程请求彼此资源——死锁:
public class Test01 {
public static void main(String[] args) {
final StringBuffer s1 = new StringBuffer();
final StringBuffer s2 = new StringBuffer();
new Thread() {
public void run() {
synchronized (s1) {
s2.append("A");
// 下面加上后会一定导致死锁
// 不加也可能导致死锁
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// throw new RuntimeException(e);
// }
synchronized (s2) {
s2.append("B");
System.out.println("一,s1 = " + s1);
System.out.println("一,s2 = " + s2);
}
}
}
}.start();
new Thread() {
public void run() {
synchronized (s2) {
s2.append("C");
synchronized (s1) {
s1.append("D");
System.out.println("二,s1 = " + s1);
System.out.println("二,s2 = " + s2);
}
}
}
}.start();
}
}
同步的范围——共享数据
释放锁
synchronized(Singleton.class)
Lock
synchronized VS Lock
线程的通信——wait()、notify()
例1——生产者、消费者:
class Clerk { // 售货员
private int product = 0;
public synchronized void addProduct() {
if (product >= 20) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
product++;
System.out.println("生产者生产了第" + product + "个产品");
notifyAll();
}
}
public synchronized void getProduct() {
if (this.product <= 0) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println("消费者取走了第" +product + "个产品");
product--;
notifyAll();
}
}
}
class Productor implements Runnable { // 生产者
Clerk clerk;
public Productor(Clerk clerk) {
this.clerk = clerk;
}
public void run() {
System.out.println("生产者开始生产产品");
while (true) {
try {
Thread.sleep((int) Math.random() * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
clerk.addProduct();
}
}
}
class Consumer implements Runnable { // 消费者
Clerk clerk;
public Consumer(Clerk clerk) {
this.clerk = clerk;
}
public void run() {
System.out.println("消费者开始取走产品");
while (true) {
try {
Thread.sleep((int) Math.random() * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
clerk.getProduct();
}
}
}
public class Test01 {
public static void main(String[] args) {
Clerk clerk = new Clerk();
Thread productorThread = new Thread(new Productor(clerk));
Thread consumerThread = new Thread(new Consumer(clerk));
productorThread.start();
consumerThread.start();
}
}
例2:
public class scratch {
// 当前要打印的数字
private static int current = 1;
// 同步锁对象
private static final Object lock = new Object();
public static void main(String[] args) {
scratch alternatePrinting = new scratch();
Thread thread1 = new Thread(() -> {
while (current <= 100) {
synchronized (lock) {
if (current % 2 == 0) {
System.out.println("线程 1:" + current);
current++;
} else {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
Thread thread2 = new Thread(() -> {
while (current <= 100) {
synchronized (lock) {
if (current % 2 != 0) {
System.out.println("线程 2:" + current);
current++;
} else {
lock.notify();
}
}
}
});
// 启动线程
thread1.start();
thread2.start();
// 等待线程执行完毕
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
方式三:实现Callable接口
import java.io.File;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Test01 implements Callable<Long> {
private String fileName;
public Test01(String fileName) {
// 构造函数,用于接收文件名
this.fileName = fileName;
}
/**
* 计算文件大小并返回
* @return 文件的大小
* @throws Exception 如果文件不存在或不是一个正常文件
*/
@Override
public Long call() throws Exception {
File f = new File(fileName);
// 判断文件是否存在且为正常文件
if (f.exists() && f.isFile()) {
return f.length();
} else {
return null;
}
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
FutureTask<Long> task = new FutureTask<>(new Test01("D:\\Desktop\\1.txt"));
Thread thread = new Thread(task);
thread.start();
// 等待结果返回
System.out.println(task.get());
}
}
FutureTask与Callable关系
方式四:线程池
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test01 {
public static void main(String[] args) {
// 创建一个固定大小为 3 的线程池
ExecutorService executor = Executors.newFixedThreadPool(3);
// 提交任务给线程池
for (int i = 1; i <= 5; i++) {
Runnable task = new Task(i);
executor.execute(task);
}
// 关闭线程池
executor.shutdown();
}
static class Task implements Runnable {
private int taskId;
public Task(int taskId) {
this.taskId = taskId;
}
@Override
public void run() {
System.out.println("Task " + taskId + " is running in thread " + Thread.currentThread().getName());
}
}
}
线程池中线程 系统自动调用:
执行策略
核心线程数 与 最大线程数关系
线程池状态变化
synchronized(lock)与lock.wait()关系
面试题
stop() 与 suspend()
sleep() VS wait()
wait()与suspend()区别
notify() VS notityAll()
等待线程执行完成——join()
模拟一个人生产50个玩具,每200毫秒生产一个,当生产到第20个时加入每秒吃1个馒头,共吃完3个后在接着生产的多线程。
class Sync {
static Object object = new Object();
}
class Person implements Runnable {
static int num;
@Override
public void run() {
while (num <= 50) {
try {
Thread.sleep(200);
System.out.println("已经生产了:" + num++);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (num == 20) {
// 使用 synchronized 关键字来保护对 num 的操作
synchronized (Sync.object) {
Sync.object.notify();
}
}
}
}
}
class Food implements Runnable {
int num = 1;
@Override
public void run() {
try {
// 使用 synchronized 关键字来保护对 num 的操作
synchronized (Sync.object) {
Sync.object.wait();
}
while (Person.num <= 50) {
synchronized (Sync.object) {
try {
Thread.sleep(1000);
System.out.println("已经吃了馒头:" + num++);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
public class Test01 extends Thread {
public static void main(String[] args) throws InterruptedException {
Person person = new Person();
Food food = new Food();
Thread thread = new Thread(person);
Thread thread1 = new Thread(food);
thread.start();
thread1.start();
}
}
启动两个线程对一个数字i操作
方式一:
public class Test01 {
static int i;
static final Object lock = new Object();
public static void main(String[] args) {
new Thread() {
@Override
public void run() {
for (int j = 0; j < 20; j++) {
synchronized (lock) {
System.out.println("加之后:i = " + ++i);
}
}
}
}.start();
new Thread() {
@Override
public void run() {
for (int j = 0; j < 20; j++) {
synchronized (lock) {
System.out.println("减之后:i = " + --i);
}
}
}
}.start();
}
}
方式二:
import java.util.concurrent.locks.ReentrantLock;
public class Test01 {
static int i;
static final ReentrantLock lock=new ReentrantLock();
public static void main(String[] args) {
new Thread() {
@Override
public void run() {
for (int j = 0; j < 20; j++) {
lock.lock();
System.out.println("加之后:i = " + ++i);
lock.unlock();
}
}
}.start();
new Thread() {
@Override
public void run() {
for (int j = 0; j < 20; j++) {
lock.lock();
System.out.println("减之后:i = " + --i);
lock.unlock();
}
}
}.start();
}
}
第9章_Java常用类
String类
String对象的创建
内存展示(重要)
地址码合集展示
class Person {
String name;
}
class Test01 {
public static void main(String[] args) {
Person p1 = new Person();
p1.name = "atguigu";
Person p2 = new Person();
p2.name = "atguigu";
String a = "atguigu";
String b = "atguigu";
String c = new String("atguigu");
String d = new String("atguigu");
System.out.println(System.identityHashCode(p1.name)); // 2101973421
System.out.println(System.identityHashCode(p2.name)); // 2101973421
System.out.println(System.identityHashCode(a)); // 2101973421
System.out.println(System.identityHashCode(b)); // 2101973421
System.out.println(System.identityHashCode(c)); // 685325104
System.out.println(System.identityHashCode(d)); // 460141958
}
}
例题
字符串拼接——intern()
intern()问题
传String形参问题
详见Java基础内容中的:值传递、引用传递
good and best
Java只有值传递
String常用方法
例子:
parseInt、valueOf
String(char[])、toCharArray()
StringBuffer类
StringBuffer类常用方法——方法链
方法链
StringBuilder VS StringBuffer
System.currentTimeMillis——获取毫秒
String——面试题
String = null问题
问题1:
String str = null;
StringBuffer sb = new StringBuffer();
sb.append(str);
System.out.println("sb = " + sb); // sb = null
System.out.println(sb.length()); // 4
问题2:
String中 == 与 equals 问题
详见:Java基础—— == 与 equals
日期时间API(旧)
currentTimeMillis()
Date类
import java.util.Date;
Date date = new Date();
System.out.println(date);
System.out.println(System.currentTimeMillis());
System.out.println(date.getTime());
Date date1 = new Date(date.getTime());
System.out.println(date1.getTime());
System.out.println(date1.toString());
SimpleDateFormat类(yy、MM——格式)
Date date = new Date(); // 产生一个Date实例
// 产生一个formater格式化的实例
SimpleDateFormat formater = new SimpleDateFormat();
System.out.println(formater.format(date));// 打印输出默认的格式
SimpleDateFormat formater2 = new SimpleDateFormat("yyyy年MM月dd日 EEE HH:mm:ss ");
System.out.println(formater2.format(date));
try {
// 实例化一个指定的格式对象
Date date2 = formater2.parse("2008年08月08日 星期一 08:08:08");
// 将指定的日期解析后格式化按指定的格式输出
System.out.println(date2.toString());
} catch (ParseException e) {
e.printStackTrace();
}
Calendar类
Calendar calendar = Calendar.getInstance();
Date date = new Date();
calendar.setTime(date);
calendar.set(Calendar.DAY_OF_MONTH, 8);
System.out.println("当前时间日设置为8后,时间是:" + calendar.getTime());
calendar.add(Calendar.HOUR, 2);
System.out.println("当前时间加2小时后,时间是:" + calendar.getTime());
calendar.add(Calendar.MONTH, -2);
System.out.println("当前日期减2个月后,时间是:" + calendar.getTime());
日期时间API(新)
LocalDateTime
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class LocalDateTimeExample {
public static void main(String[] args) {
// 获取当前日期和时间
LocalDateTime currentDateTime = LocalDateTime.now();
System.out.println("当前日期和时间: " + currentDateTime);
// 获取日期
int day = currentDateTime.getDayOfMonth();
System.out.println("日期: " + day);
// 获取小时
int hour = currentDateTime.getHour();
System.out.println("小时: " + hour);
}
}
DateTimeFormatter
LocalDateTime localDateTime= LocalDateTime.now();
System.out.println(DateTimeFormatter.ofPattern("yy年--MM月").format(localDateTime));
其他类及对应API
Duration——计算“时间”间隔
Period——计算“日期”间隔
Java比较器
Comparable
class Goods implements Comparable {
private String name;
private double price;
//按照价格,比较商品的大小
@Override
public int compareTo(Object o) {
if (o instanceof Goods) {
Goods other = (Goods) o;
if (this.price > other.price) {
return 1;
} else if (this.price < other.price) {
return -1;
}
return 0;
}
throw new RuntimeException("输入的数据类型不一致");
}
public Goods(String name, double price) {
this.name = name;
this.price = price;
}
@Override
public String toString() {
return "Goods{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
}
public class Test01 {
public static void main(String[] args) {
Goods[] all = new Goods[4];
all[0] = new Goods("《红楼梦》", 100);
all[1] = new Goods("《西游记》", 80);
all[2] = new Goods("《三国演义》", 140);
all[3] = new Goods("《水浒传》", 120);
Arrays.sort(all);
System.out.println(Arrays.toString(all));
}
}
Comparator
import java.util.Arrays;
import java.util.Comparator;
class Goods implements Comparable {
private String name;
private double price;
//按照价格,比较商品的大小
@Override
public int compareTo(Object o) {
if (o instanceof Goods) {
Goods other = (Goods) o;
if (this.price > other.price) {
return 1;
} else if (this.price < other.price) {
return -1;
}
return 0;
}
throw new RuntimeException("输入的数据类型不一致");
}
public Goods(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Goods{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
}
public class Test01 {
public static void main(String[] args) {
Goods[] all = new Goods[4];
all[0] = new Goods("War and Peace", 100);
all[1] = new Goods("Childhood", 80);
all[2] = new Goods("Scarlet and Black", 140);
all[3] = new Goods("Notre Dame de Paris", 120);
Comparator comparator = new Comparator() {
@Override
public int compare(Object o1, Object o2) {
Goods g1 = (Goods) o1;
Goods g2 = (Goods) o2;
return g1.getName().compareTo(g2.getName());
}
};
Arrays.sort(all, comparator);
System.out.println(Arrays.toString(all));
}
}
Comparable VS Comparator
System类
String javaVersion = System.getProperty("java.version");
System.out.println("java的version:" + javaVersion);
String javaHome = System.getProperty("java.home");
System.out.println("java的home:" + javaHome);
String osName = System.getProperty("os.name");
System.out.println("os的name:" + osName);
String osVersion = System.getProperty("os.version");
System.out.println("os的version:" + osVersion);
String userName = System.getProperty("user.name");
System.out.println("user的name:" + userName);
String userHome = System.getProperty("user.home");
System.out.println("user的home:" + userHome);
String userDir = System.getProperty("user.dir");
System.out.println("user的dir:" + userDir);
Math类
BigInteger类
BigInteger bigInteger = new BigInteger("11111111111");
BigInteger bigInteger1 = new BigInteger("11");
bigInteger = bigInteger.subtract(bigInteger1);
System.out.println(bigInteger);
BigDecimal类
BigDecimal bd = new BigDecimal("12435.351");
BigDecimal bd2 = new BigDecimal("11");
System.out.println(bd.divide(bd2, BigDecimal.ROUND_HALF_UP));
System.out.println(bd.divide(bd2, 5, BigDecimal.ROUND_HALF_UP));
面试题
1.
2.
3.
4.String VS StringBuffer
第10章_枚举类&注解
enum枚举类
旧——自定义枚举类
新——enum
注解(Annotation)
@author
@Override
代替配置文件
自定义 Annotation——@interface
元注解——@Target
@Retention
@Target
@Documented
反射获取注解信息
可重复的注解
新@Target
第11章_Java集合
Collection接口继承树
Map接口继承树
Collection 接口
Collection 接口方法
Iterator迭代器接口
// 创建一个字符串列表
List<String> stringList = new ArrayList<>();
stringList.add("Apple");
stringList.add("Banana");
stringList.add("Orange");
// 使用 Iterator 遍历列表
Iterator<String> iterator = stringList.iterator();
while (iterator.hasNext()) {
String element = iterator.next();
System.out.println(element);
}
Iterator接口remove()方法
foreach
List接口
ArrayList
String[] array = {"Apple", "Banana", "Orange"};
// 使用 Arrays.asList() 将数组转换为 List
List<String> list = Arrays.asList(array);