多线程学习

多线程

进程可能包含多个线程,都会有 main 线程和 gc 线程。

// 继承 **Thread** 类,重写 **run()** 方法,创建线程对象,调用 start() 开启线程
// TestThread1 extends Thread
TestThread1 t1 = new TestThread1();
t1.start();
​
// 实现 **Runnable** 接口,重写 **run()** 方法,创建接口的实现类对象,创建 Thread 调用 start() 启动线程
// 方便同一个对象被多个线程使用,避免单继承的局限性
// TestThread2 implements Runnable
TestThread2 t2 = new TestThread2();
new Thread(t2).start();
​
// 实现 **Callable ** 接口
package com.wang.ThreadDemo;
​
import java.util.concurrent.*;
​
public class TestCallable implements Callable {
    @Override
    public Object call() throws Exception {
        return "Hello World!";
    }
​
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        TestCallable t1 = new TestCallable();
        TestCallable t2 = new TestCallable();
        // 创建执行服务
        ExecutorService ser = Executors.newFixedThreadPool(3);
        // 提交执行
        // ser.execute(Runnable command) 执行命令,无返回值
        Future submit1 = ser.submit(t1);
        Future submit2 = ser.submit(t2);
        // 获取结果
        String res1 = (String)submit1.get();
        String res2 = (String)submit2.get();
        // 关闭服务
        ser.shutdownNow();
    }
}

静态代理模式

线程底部是 静态代理模式

// 真实对象 和 代理对象 实现同一个接口
// 代理对象 代理 真实角色
// 好处:代理对象可以做很多事情,真实对象专注做自己的事情

lamda表达式

函数式接口:任何接口,如果只包含唯一一个抽象方法,就是函数式接口

对于函数式接口,可通过lamda表达式来创建该接口的对象

public class TestLamda {
    // 3.静态内部类
    static class Tface2 implements Itface{
        @Override
        public void lamda() {
            System.out.println("i like lamda2!");
        }
    }
​
    public static void main(String[] args) {
        Itface tface = new Tface1();
        tface.lamda();
​
        tface = new Tface2();
        tface.lamda();
​
        // 4.局部内部类
        class Tface3 implements Itface{
            @Override
            public void lamda() {
                System.out.println("i like lamda3!");
            }
        }
        tface = new Tface3();
        tface.lamda();
​
        // 5.匿名内部类,必须借助接口或者父类
        tface = new Itface() {
            @Override
            public void lamda() {
                System.out.println("i like lamda4!");
            }
        };
        tface.lamda();
​
        // 6.lamda表达式
        tface = () -> {
            System.out.println("i like lamda5!");
        };
        tface.lamda();
    }
}
// 1.定义一个函数式接口
interface Itface{
    void lamda();
}
​
// 2.外部实现类
class Tface1 implements Itface{
    @Override
    public void lamda() {
        System.out.println("i like lamda1!");
    }
}

去掉类名,去掉方法名,去掉参数类型,只有一个参数简化括号,只有单行代码简化花括号

上述变成:tface = () -> System.out.println("i like lamda5!");

线程状态

新生状态(new),就绪状态(start),运行状态,死亡状态, 阻塞状态(sleep,wait)

每个对象都有一把锁,sleep不会释放锁,抱着锁睡觉

线程礼让 yield,礼让不一定成功 Thread.yield();

合并线程 Join,thread.join(); 调用插队线程的join方法。

getState() 获取线程状态,getPriority() 获取线程优先级,优先级从1-10

线程分为用户线程和守护线程,setDaemon 设置守护线程

线程同步

车站买票、银行取钱、ArrayList() 等都是典型的线程不同步问题。

synchronized 控制对对象的访问,每个对象对应一把锁,可以锁 代码块方法

synchronized (obj) {},obj称为同步监视器,推荐使用共享资源作为同步监视器

package com.wang.ThreadDemo;
​
import java.util.ArrayList;
import java.util.List;
​
public class ThreadSynchronized {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        // 不加锁
//        for (int i = 0; i < 50000; i++) {
//            new Thread(() -> {
//                list.add(Thread.currentThread().getName());
//            }).start();
//        }
​
        // 给list加锁
        for (int i = 0; i < 50000; i++) {
            new Thread(() -> {
                synchronized (list) {
                    list.add(Thread.currentThread().getName());
                }
            }).start();
        }
​
        // 休眠,主线程等待其他线程运行完
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(list.size());
    }
}

某一个同步块同时拥有两个以上对象的锁,相互等待对方释放资源,造成死锁现象。 持有且等待

产生死锁的四个必要条件:

互斥条件、请求与保持条件、不剥夺条件、循环等待条件

Lock() 显式定义同步锁 :ReentrantLock 可重入锁

class A {
    private final ReentrantLock lock = new ReentrantLock();
    public void m() {
        lock.lock();
        try {
            // 保证线程安全的代码
        } finally{
            lock.unlock();
        }
    }
}

生产者消费者问题

管程法:利用缓冲区解决生产者消费者问题,实现生产者和消费者之间的通信

信号灯法:并发协作模型 “生产者 / 消费者模式” ,通过标志位方式来等待(wait)和唤醒(notify)

注解

Annotation Type 常见注解:@Override、@Deprecated、@SuppressWarnings("all")

元注解meta-annotation:@Target、@Retention(SOURCE < CLASS < RUNTIME)@Documented、@Inherited

package com.wang;
​
import java.lang.annotation.*;
​
public class TestAnno {
    @MyAnnotation(name = "wang", id = 3)
    public void test() {
        
    }
}
// 表示注解可以用在哪些地方
@Target(value = {ElementType.METHOD,ElementType.TYPE})
// 表示注解在什么地方有效   RUNTIME > CLASS > SOURCE
@Retention(value = RetentionPolicy.RUNTIME) 
// 表示注解是否生成在JavaDoc中
@Documented
// 表示是否继承父类
@Inherited    
@interface MyAnnotation{
    // 注解的参数:参数类型 + 参数名 ();
    String name() default "";
    int id() default -1;
}

反射

一个类在内存中只有一个Class对象

一个类被加载后,类的整个结构都会被封装在Class对象中

package com.wang;
​
public class Reflection_ {
    public static void main(String[] args) throws ClassNotFoundException {
        // 1.通过类名.class获得
        System.out.println(Student.class);
        
        // 2.通过对象获得
        Person p = new Student("小明");
        System.out.println(p.getClass());
​
        // 3.通过Class的静态方法forName获得
        System.out.println(Class.forName("com.wang.Student"));
​
        // 4.基本内置类型的包装类有一个Type属性
        System.out.println(Integer.TYPE);
​
        System.out.println(p.getClass().getSuperclass());
    }
}
​
class Person{
    String name;
    public Person() {
    }
    public Person(String name) {
        this.name = name;
    }
​
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}
class Student extends Person{
    public Student(String name) {
        this.name = name;
    }
}
class Teacher extends Person{
    public Teacher(String name) {
        this.name = name;
    }
}
        System.out.println(Object.class);   // class java.lang.Object
        System.out.println(Comparable.class); // interface java.lang.Comparable
        System.out.println(String[].class); // class [Ljava.lang.String;
        System.out.println(int[][].class);  // class [[I
        System.out.println(Override.class); // interface java.lang.Override
        System.out.println(ElementType.class); // class java.lang.annotation.ElementType
        System.out.println(Integer.class);  // class java.lang.Integer
        System.out.println(void.class);     // void
        System.out.println(Class.class);    // class java.lang.Class

类加载

加载到内存,产生一个类对应的Class对象

链接,链接结束后,为类变量分配内存,静态变量完成默认初始化,常量存入常量池

初始化,执行<clinit>(),按顺序执行静态初始化和静态代码块

不会产生类的引用的方法:

  1. 子类调用父类的静态变量或静态方法,不会导致子类初始化

  2. 数组定义类引用,不会触发此类的初始化

  3. 引用常量不会触发此类的初始化

// 系统类加载器->扩展类加载器->根加载器(引导类加载器)
// 获取系统类加载器可以加载的路径
System.getProperty("java.class.path");

反射获取类信息

// getFields                    获取本类public的属性
// getDeclaredFields            获取本类所有的属性
// getMethods                   获取本类及父类所有public的方法 *
// getDeclaredMethods           获取本类的所有方法
// getConstructors()            获取本类public构造方法
// getDeclaredConstructors()    获取本类所有构造方法
​
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
​
public class Ref {
    public static void main(String[] args) throws Exception {
        Class c1 = Class.forName("com.wang.Person");
        // 类必须存在无参构造器
        Person p1 = (Person) c1.newInstance();
        System.out.println(p1);
        // 通过构造器创建对象
        Constructor constructor = c1.getDeclaredConstructor(String.class);
        Person p2 = (Person)constructor.newInstance("wang");
        System.out.println(p2);
        // 反射调用方法
        Method run = c1.getDeclaredMethod("run", String.class, int.class);
        run.setAccessible(true); // 爆破
        run.invoke(p2, "wang", 3);
        // 改变私有属性
        Field age = c1.getDeclaredField("age");
        age.setAccessible(true);
        age.set(p1, 12);
        System.out.println(p1.getAge());
    }
}

反射获取泛型

    public void test01(Map<String,Person> map) {
​
    }
    public Map<String, Person> test02(){
        System.out.println("test02");
        return null;
    }
    public static void main(String[] args) throws Exception {
        Method method = Ref.class.getMethod("test01", Map.class);
        Type[] genericParameterTypes = method.getGenericParameterTypes();
        for (Type genericParameterType : genericParameterTypes) {
            System.out.println(genericParameterType);
            if (genericParameterType instanceof ParameterizedType) {
                Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println(actualTypeArgument);
                }
            }
        }
        Method method1 = Ref.class.getMethod("test02", null);
        Type genericReturnType = method1.getGenericReturnType();
        if (genericReturnType instanceof ParameterizedType) {
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println(actualTypeArgument);
            }
        }
    }

getAnnotation 获取注解 ** 还会回来看的

posted on 2022-02-27 17:58  木非辛  阅读(30)  评论(0)    收藏  举报