
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:最常用的方式,适用于已知类名的情况。
- 通过对象的 getClass () 方法:如果已经有对象实例,可以通过该方法获取其对应的
Class对象。
- 通过 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();
}
}
}