跳转至

图片

javaSE(六)多线程与反射

一、多线程

什么是多线程

在 Java 中,线程是程序执行的最小单元,多线程指的是在一个程序(进程)中同时运行多个线程,每个线程执行独立的任务。例如,在一个音乐播放器程序中,一个线程可以负责播放音乐,另一个线程可以负责处理用户界面的交互,如暂停、播放、调整音量等操作。

2.多线程的实现方式

  • 继承 Thread 类:通过创建一个类继承自Thread类,并重写其run()方法,在run()方法中定义线程要执行的任务。
class MyThread extends Thread {
    @Override
    public void run() {
        // 线程执行的代码
        System.out.println("MyThread is running");
    }
}

public class Main {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start(); // 启动线程
    }
}
  • 实现 Runnable 接口:定义一个类实现Runnable接口,实现其run()方法。然后将该类的实例作为参数传递给Thread类的构造函数来创建线程对象。
class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("MyRunnable is running");
    }
}

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable());
        thread.start();
    }
}
  • 实现 Callable 接口(Java 5 及以后):与Runnable类似,但Callable可以有返回值并且可以抛出异常。通常配合FutureTask来使用。
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

class MyCallable implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        return 42; // 返回结果
    }
}

public class Main {
    public static void main(String[] args) {
        FutureTask<Integer> futureTask = new FutureTask<>(new MyCallable());
        Thread thread = new Thread(futureTask);
        thread.start();
        try {
            Integer result = futureTask.get(); // 获取返回值
            System.out.println("Result: " + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3.线程的生命周期

  • 新建(New):使用new关键字创建线程对象后,线程处于新建状态。
  • 就绪(Runnable):调用start()方法后,线程进入就绪状态,等待 CPU 调度。
  • 运行(Running):当 CPU 调度到该线程时,线程进入运行状态,执行run()方法中的代码。
  • 阻塞(Blocked):线程因某些原因(如等待锁、I/O 操作等)暂停执行,进入阻塞状态,此时不占用 CPU 资源。
  • 死亡(Terminated):线程执行完run()方法中的代码,或者因异常终止,进入死亡状态。

4.线程同步

当多个线程访问共享资源时,可能会出现数据不一致的问题,例如多个线程同时对一个变量进行读写操作。为了解决这个问题,需要使用线程同步机制。

  • synchronized 关键字:可以用来修饰方法或代码块,确保同一时刻只有一个线程能够访问被同步的代码
class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public int getCount() {
        return count;
    }
}
  • Lock 接口:Java 5 引入的java.util.concurrent.locks.Lock接口,提供了比synchronized更灵活的锁机制,例如可重入锁(ReentrantLock)。
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class Counter {
    private int count = 0;
    private Lock lock = new ReentrantLock();

    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }

    public int getCount() {
        return count;
    }
}

反射

1.什么是反射

反射是 Java 的一项强大特性,它允许程序在运行时获取类的信息,包括类的属性、方法、构造函数等,并可以动态地创建对象、调用方法、访问和修改属性。例如,在开发框架(如 Spring)时,反射机制被广泛用于实现依赖注入和 AOP(面向切面编程)等功能。

2. 获取 Class 对象的方式

  • 通过类名.class:最常用的方式,适用于已知类名的情况。
Class<?> clazz = String.class;
  • 通过对象的 getClass () 方法:如果已经有对象实例,可以通过该方法获取其对应的Class对象。
String str = "Hello";
Class<?> clazz = str.getClass();
  • 通过 Class.forName () 方法:可以根据类的全限定名(包名 + 类名)获取Class对象,常用于加载配置文件中指定的类。
try {
    Class<?> clazz = Class.forName("java.lang.String");
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

3. 使用反射创建对象

  • 通过无参构造函数
try {
    Class<?> clazz = String.class;
    Object obj = clazz.getConstructor().newInstance();
} catch (Exception e) {
    e.printStackTrace();
}
  • 通过有参构造函数
import java.lang.reflect.Constructor;

class Person {
    private String name;
    private int age;

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

public class Main {
    public static void main(String[] args) {
        try {
            Class<?> clazz = Person.class;
            Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
            Object obj = constructor.newInstance("Alice", 25);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

4. 使用反射调用方法

import java.lang.reflect.Method;

class Calculator {
    public int add(int a, int b) {
        return a + b;
    }
}

public class Main {
    public static void main(String[] args) {
        try {
            Class<?> clazz = Calculator.class;
            Calculator calculator = (Calculator) clazz.getConstructor().newInstance();
            Method method = clazz.getMethod("add", int.class, int.class);
            Object result = method.invoke(calculator, 3, 5);
            System.out.println("Result: " + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

5. 使用反射访问和修改属性

import java.lang.reflect.Field;

class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }
}

public class Main {
    public static void main(String[] args) {
        try {
            Class<?> clazz = Person.class;
            Person person = (Person) clazz.getConstructor(String.class).newInstance("Bob");
            Field field = clazz.getDeclaredField("name");
            field.setAccessible(true); // 允许访问私有属性
            field.set(person, "Alice");
            System.out.println("Name: " + field.get(person));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}