线程的基本使用
Java 中线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。一个进程中可以并发多个线程,多条线程并行执行不同的任务。
创建线程的方式
继承 Thread 类的方式:
定义一个线程类,继承 Thread 类,重写 run () 方法,将线程要执行的任务写在 run () 方法中,然后创建该类的实例,调用 start () 方法启动线程。
实现 Runnable 接口的方式:
定义一个类,实现 Runnable 接口,实现 run () 方法,将线程要执行的任务写在 run () 方法中,然后创建该类的实例,再创建一个 Thread 类的实例,将 Runnable 实例作为参数传递给 Thread 构造器,最后调用 Thread 实例的 start () 方法启动线程。
线程的几种状态
新建(New):创建了一个线程对象,但还没有调用 start () 方法。
就绪(Runnable):调用了 start () 方法,等待 CPU 的调度。
运行(Running):获得了 CPU 的执行权,正在执行 run () 方法中的代码。
阻塞(Blocked):由于某些原因放弃了 CPU 的执行权,暂停执行。例如等待输入输出完成,或者等待获取同步锁。
终止(Terminated):run () 方法执行完毕或者出现异常而结束。
线程的主要概念
线程同步:当多个线程访问共享资源时,为了保证数据的一致性和完整性,需要使用同步机制来协调线程之间的操作顺序和执行时间。
线程间通信:当多个线程需要协作完成某个任务时,需要使用 wait ()、notify ()、notifyAll () 等方法来实现线程之间的交互和协调。
线程死锁:当多个线程互相持有对方需要的资源而不释放时,导致所有线程都无法继续执行的情况。
线程控制:当需要暂停、停止或恢复某个线程时,可以使用 suspend ()、stop ()、resume () 等方法来控制线程的状态。
代码示例
通过实现 Runnable 接口
// 定义一个类,实现 Runnable 接口
class PrintNumberRunnable implements Runnable {
private int number;
// 重写 run () 方法
public void run() {
while(number<100){
System.out.println(Thread.currentThread().getName()+":输出数字 "+number++);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// 创建该类的实例
PrintNumberRunnable printNumberRunnable = new PrintNumberRunnable();
// 创建一个 Thread 类的实例
Thread thread = new Thread(printNumberRunnable);
// 给线程设置名字
thread.setName("printNumberRunnable");
// 调用 start () 方法启动线程
thread.start();
定义一个类,实现 Runnable 接口,重写 run () 方法,将线程要执行的任务写在 run () 方法中,然后创建该类的实例,再创建一个 Thread 类的实例,将 Runnable 实例作为参数传递给 Thread 构造器,最后调用 Thread 实例的 start () 方法启动线程。
通过继承 Thread 类
// 定义一个类,继承 Thread 类
class PrintNumberThread extends Thread {
private int number;
// 重写 run () 方法
public void run(){
while(number<100){
System.out.println(Thread.currentThread().getName()+":输出数字 "+number++);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// 创建该类的实例
PrintNumberThread printNumberThread = new PrintNumberThread();
// 给线程设置名字
printNumberThread.setName("printNumberThread");
// 调用 start () 方法启动线程
printNumberThread.start();
定义一个类,继承 Thread 类,重写 run () 方法,将线程要执行的任务写在 run () 方法中,然后创建该类的实例,调用该实例的 start () 方法启动线程。
通过 Callable 和 Future 接口
// 定义一个类,实现 Callable 接口
class SumTask implements Callable<Integer> {
private int n;
public SumTask(int n) {
this.n = n;
}
// 重写 call () 方法
public Integer call() throws Exception {
int sum = 0;
for (int i = 1; i <= n; i++) {
sum += i;
}
return sum;
}
}
// 创建该类的实例
SumTask sumTask = new SumTask(100);
// 创建一个 ExecutorService 类的实例
ExecutorService executorService = Executors.newSingleThreadExecutor();
// 使用 submit () 方法提交 Callable 实例,并返回一个 Future 对象
Future<Integer> future = executorService.submit(sumTask);
// 调用 Future 对象的 get () 方法获取线程的返回值
try {
System.out.println("1+2+...+100=" + future.get());
} catch (Exception e) {
e.printStackTrace();
}
// 关闭线程池
executorService.shutdown();
定义一个类,实现 Callable 接口,重写 call () 方法,将线程要执行的任务和返回值写在 call () 方法中,然后创建该类的实例,再创建一个 ExecutorService 类的实例,使用 submit () 方法提交 Callable 实例,并返回一个 Future 对象,最后调用 Future 对象的 get () 方法获取线程的返回值。