day24

1:多线程(理解)

(1)JDK5以后的针对线程的锁定操作和释放操作

Lock锁:
void lock(): 获取锁。
void unlock():释放锁

(2)死锁问题的描述和代码体现

public class DieLockDemo {
    public static void main(String[] args) {
        DieLock dl1 = new DieLock(true);
        DieLock dl2 = new DieLock(false);

        dl1.start();
        dl2.start();
    }
}

public class MyLock {
    // 创建两把锁对象
    public static final Object objA = new Object();
    public static final Object objB = new Object();
}

public class DieLock extends Thread {

    private boolean flag;

    public DieLock(boolean flag) {
        this.flag = flag;
    }

    @Override
    public void run() {
        if (flag) {
            synchronized (MyLock.objA) {
                System.out.println("if objA");
                synchronized (MyLock.objB) {
                    System.out.println("if objB");
                }
            }
        } else {
            synchronized (MyLock.objB) {
                System.out.println("else objB");
                synchronized (MyLock.objA) {
                    System.out.println("else objA");
                }
            }
        }
    }
}

(3)生产者和消费者多线程体现(线程间通信问题)

以学生作为资源来实现的
资源类:Student
设置数据类:SetThread(生产者)
获取数据类:GetThread(消费者)
测试类:StudentDemo
代码:
A:最基本的版本,只有一个数据。
B:改进版本,给出了不同的数据,并加入了同步机制
C:等待唤醒机制改进该程序,让数据能够实现依次的出现
wait()
notify()
notifyAll() (多生产多消费)
D:等待唤醒机制的代码优化。把数据及操作都写在了资源类中

public class Student {
    private String name;
    private int age;
    private boolean flag; // 默认情况是没有数据,如果是true,说明有数据

    public synchronized void set(String name, int age) {
        // 如果有数据,就等待
        if (this.flag) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        // 设置数据
        this.name = name;
        this.age = age;

        // 修改标记
        this.flag = true;
        this.notify();
    }

    public synchronized void get() {
        // 如果没有数据,就等待
        if (!this.flag) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        // 获取数据
        System.out.println(this.name + "---" + this.age);

        // 修改标记
        this.flag = false;
        this.notify();
    }
}

public class SetThread implements Runnable {

    private Student s;
    private int x = 0;

    public SetThread(Student s) {
        this.s = s;
    }

    @Override
    public void run() {
        while (true) {
            if (x % 2 == 0) {
                s.set("林青霞", 27);
            } else {
                s.set("刘意", 30);
            }
            x++;
        }
    }
}

public class GetThread implements Runnable {
    private Student s;

    public GetThread(Student s) {
        this.s = s;
    }

    @Override
    public void run() {
        while (true) {
            s.get();
        }
    }
}

public class StudentDemo {
    public static void main(String[] args) {
        //创建资源
        Student s = new Student();
        
        //设置和获取的类
        SetThread st = new SetThread(s);
        GetThread gt = new GetThread(s);

        //线程类
        Thread t1 = new Thread(st);
        Thread t2 = new Thread(gt);

        //启动线程
        t1.start();
        t2.start();
    }
}

(4)线程组

把多个线程组合到一起。
线程默认情况下属于main线程组

(5)线程池

线程池的好处:线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。
如何实现线程的代码呢?
A:创建一个线程池对象,控制要创建几个线程对象。
public static ExecutorService newFixedThreadPool(int nThreads)
B:这种线程池的线程可以执行:
可以执行Runnable对象或者Callable对象代表的线程
做一个类实现Runnable接口。
C:调用如下方法即可
Future submit(Runnable task)
Future submit(Callable task)
D:我就要结束,可以吗?
可以。pool.shutdown();

(6)多线程实现的第三种方案

(7)多线程的面试题

public class ThreadDemo {
    public static void main(String[] args) {
        // 继承Thread类来实现多线程
        new Thread() {
            public void run() {
                for (int x = 0; x < 100; x++) {
                    System.out.println(Thread.currentThread().getName() + ":"
                            + x);
                }
            }
        }.start();

        // 实现Runnable接口来实现多线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int x = 0; x < 100; x++) {
                    System.out.println(Thread.currentThread().getName() + ":"
                            + x);
                }
            }
        }) {
        }.start();
}

1:多线程有几种实现方案,分别是哪几种?

两种。继承Thread类、实现Runnable接口
扩展一种:实现Callable接口。这个得和线程池结合。

2:同步有几种方式,分别是什么?

两种。同步代码块、同步方法

3:启动一个线程是run()还是start()?它们的区别?

start();
run():封装了被线程执行的代码,直接调用仅仅是普通方法的调用
start():启动线程,并由JVM自动调用run()方法

4:sleep()和wait()方法的区别

sleep():必须指时间;不释放锁。
wait():可以不指定时间,也可以指定时间;释放锁。

5:为什么wait(),notify(),notifyAll()等方法都定义在Object类中

因为这些方法的调用是依赖于锁对象的,而同步代码块的锁对象是任意锁。
而Object代码任意的对象,所以,定义在这里面。
6:线程的生命周期图
新建 -- 就绪 -- 运行 -- 死亡
新建 -- 就绪 -- 运行 -- 阻塞 -- 就绪 -- 运行 -- 死亡
建议:画图解释。


图片.png

2:设计模式(理解)

(1)面试对象的常见设计原则

单一
开闭
里氏
依赖注入
接口
迪米特

(2)设计模式概述和分类

A:经验的总结
B:三类
创建型
结构型
行为型

(3)改进的设计模式

A:简单工厂模式
B:工厂方法模式
C:单例模式(掌握):
饿汉式:类一加载就创建对象
懒汉式:用的时候,才去创建对象
面试题:单例模式的思想是什么?请写一个代码体现。

开发:饿汉式(是不会出问题的单例模式)
面试:懒汉式(可能会出问题的单例模式)
A:懒加载(延迟加载)
B:线程安全问题
a:是否多线程环境 是
b:是否有共享数据 是
c:是否有多条语句操作共享数据 是

a:以下是饿汉式

public class Student {
    private Student() {}
    private static Student s = new Student();
    public static Student getStudent(){
        return s;
    }
}
public class StudentDemo {
    public static void main(String[] args) {
        Student s1 = Student.getStudent();
        Student s2 = Student.getStudent();
        System.out.println(s1 == s2);
    }
}
        b:懒汉式
public class Teacher {
    private Teacher() { }

    private static Teacher t = null;

    public synchronized static Teacher getTeacher(){
        if (t == null){
            t = new Teacher();
        }
            return t;
    }
}
public class TeacherDemo {
    public synchronized static void main(String[] args) {
        Teacher t1 = Teacher.getTeacher();
        Teacher t2 = Teacher.getTeacher();
        System.out.println(t1 == t2);
    }
}

(4)Runtime

    JDK提供的一个单例模式应用的类。
    还可以调用dos命令。

你可能感兴趣的:(day24)