Java——高级内容

 总览

知识图解

总目录

第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);

LinkedList

Vector

ArrayList  LinkedList  Vector的异同

Set接口

HashSet

重写 equals() 方法

LinkedHashSet

TreeSet VS HashSet

Map接口

Map方法

Map输出

HashMap

HashMap的扩容

HashMap面试题

两个元素的hashcode值相等,但是这两个元素不相等

Properties

例题——List内去除重复数字值

Collections方法

第12章_泛型

第13章_IO流

第14章_网络编程

第15章_Java反射机制

第16章_Java8的其它新特性

第17章_Java9&10&11新特性

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值