线程,作为程序执行的最小单元,能够让程序在同一时间内处理多个任务,避免因单任务阻塞而造成的资源浪费。无论是处理大量用户请求的服务器端应用,还是需要同时进行数据计算与 UI 交互的客户端程序,多线程都扮演着至关重要的角色。

一、线程的创建在 Java 编程中,多线程是实现并发执行的重要手段,它能让程序同时处理多个任务,提升运行效率。以下将详细介绍 Java 中创建多线程的三种常用方式,包括它们的实现步骤、优缺点及适用场景。

1、通过继承Thread的方式实现Thread 类是 Java 中用于线程操作的基础类,通过继承该类可以直接创建线程。

实现步骤:

自定义一个类,继承 Thread 类。重写 Thread 类中的 run () 方法,在该方法中编写线程要执行的任务代码。创建自定义类的实例对象。调用实例对象的 start () 方法启动线程(注意:不可直接调用 run () 方法,否则会当作普通方法执行,无法实现多线程并发)。

package org.example;

public class MyThread extends Thread{

// 构造方法,用于设置线程名称

public MyThread() {}

public MyThread(String name) {

super(name);

}

@Override

public void run() {

// 线程执行的任务:输出10条信息

for (int i = 0; i < 10; i++) {

try {

Thread.sleep(100); // 休眠100毫秒

} catch (InterruptedException e) {

throw new RuntimeException(e);

}

System.out.println(getName() + "hello" + i);

}

}

}

// 启动线程

public class Main {

public static void main(String[] args) {

MyThread thread1 = new MyThread("线程1");

MyThread thread2 = new MyThread("线程2");

thread1.start();

thread2.start();

}

}

优点:

编程简单直接,可直接使用 Thread 类中的方法(如 getName () 获取线程名称)。缺点:

扩展性较差,由于 Java 是单继承机制,继承了 Thread 类后就不能再继承其他类。适用场景:简单的多线程任务,且不需要继承其他类的场景。

2、 通过Runnable 接口实现Runnable 接口是 Java 中定义线程任务的接口,通过实现该接口可以更灵活地创建线程。

实现步骤:

自定义一个类,实现 Runnable 接口。重写 Runnable 接口中的 run () 方法,编写线程任务代码。创建自定义类的实例对象(该对象表示线程要执行的任务)。创建 Thread 类的实例对象,将自定义类的实例作为参数传入 Thread 的构造方法中。调用 Thread 实例的 start () 方法启动线程。

package org.example;

public class MyRunnable implements Runnable{

@Override

public void run() {

// 线程执行的任务:输出100条信息

for (int i = 0; i < 100; i++) {

Thread t = Thread.currentThread(); // 获取当前线程对象

System.out.println(t.getName() + "hello" + i);

}

}

}

// 启动线程

public class Main {

public static void main(String[] args) {

MyRunnable myRunnable = new MyRunnable();

Thread thread1 = new Thread(myRunnable, "线程1");

Thread thread2 = new Thread(myRunnable, "线程2");

thread1.start();

thread2.start();

}

}

优点:

扩展性强,实现 Runnable 接口的同时还可以继承其他类。适合多个线程共享同一个任务资源的场景。缺点:

编程相对复杂,不能直接使用 Thread 类中的方法,需通过 Thread.currentThread () 获取当前线程对象后再调用相关方法。适用场景:多线程共享资源的场景,或需要继承其他类的场景。

3、通过 Callable 接口结合 FutureTask 类实现Callable 接口与 Runnable 接口类似,但它可以获取线程执行的返回结果,适用于需要获取线程执行结果的场景。

实现步骤:

自定义一个类,实现 Callable 接口(需指定返回值类型)。重写 Callable 接口中的 call () 方法,编写线程任务代码,并返回执行结果。创建自定义类的实例对象(表示线程任务)。创建 FutureTask 类的实例对象,将 Callable 实例作为参数传入(用于管理线程执行结果)。创建 Thread 类的实例对象,将 FutureTask 实例作为参数传入。调用 Thread 实例的 start () 方法启动线程。调用 FutureTask 实例的 get () 方法获取线程执行的返回结果

package org.example;

import java.util.concurrent.Callable;

public class MyCallable implements Callable {

@Override

public Integer call() throws Exception {

// 线程执行的任务:计算1到100的和

int sum = 0;

for (int i = 0; i futureTask = new FutureTask<>(myCallable);

Thread thread = new Thread(futureTask);

thread.start();

Integer result = futureTask.get(); // 获取线程执行结果

System.out.println(result);

}

}

优点:

可以获取线程执行的返回结果,功能更强大。扩展性强,实现 Callable 接口的同时可以继承其他类。缺点:

编程最为复杂,需要结合 FutureTask 类来管理返回结果。适用场景:需要获取线程执行结果的场景,如多线程计算并汇总结果的任务。

二、线程的常见方法线程的方法是控制线程行为的关键,掌握这些方法能让我们更好地管理线程的执行顺序、状态等。以下将详细介绍 Java 线程中常见的方法及其使用场景。

线程的常见方法如下:

1、getName() 返回该线程的名称2、setName(String name) 设置线程的名字3、static Thread currentThread() 获取当前线程对象4、static void sleep(long time) 让线程休眠的时间,单位是毫秒5、setPriority(int newPriority) 设置线程的优先级 6、final int getPriority()获取线程的优先级7、final void setDaemon(boolean on)8、static void yield()出让线程/礼让线程9、final void join()插入线程/插队线程1、线程名称相关方法String getName():返回当前线程的名称。若未手动设置,线程会有默认名称(格式为 “Thread-x”,x 为数字)。void setName(String name):设置线程的名称,也可通过线程的构造方法设置名称。

// 通过构造方法设置名称

MyThread thread1 = new MyThread("飞机");

// 通过setName()方法设置名称

MyThread thread2 = new MyThread();

thread2.setName("坦克");

2、获取当前线程对象static Thread currentThread():获取当前正在执行的线程对象。在 main 方法中调用时,获取的是 main 线程对象。

// 在Runnable实现类的run()方法中获取当前线程

public class MyRunnable implements Runnable{

@Override

public void run() {

Thread t = Thread.currentThread();

System.out.println(t.getName());

}

}

3、线程休眠static void sleep(long time):让当前线程休眠指定的时间(单位为毫秒),休眠期间线程会释放 CPU 资源,时间结束后重新参与 CPU 调度。

@Override

public void run() {

for (int i = 0; i < 10; i++) {

try {

Thread.sleep(100); // 休眠100毫秒

} catch (InterruptedException e) {

throw new RuntimeException(e);

}

System.out.println(getName() + "hello" + i);

}

}

4、线程优先级setPriority(int newPriority):设置线程的优先级,优先级范围为 1-10,默认优先级为 5,优先级越高,线程获取 CPU 资源的概率越大(但不保证一定先执行)。final int getPriority():获取线程的优先级。

MyRunnable myRunnable = new MyRunnable();

Thread thread1 = new Thread(myRunnable, "飞机");

Thread thread2 = new Thread(myRunnable, "坦克");

thread1.setPriority(10); // 设置最高优先级

thread2.setPriority(1); // 设置最低优先级

thread1.start();

thread2.start();

5、守护线程final void setDaemon(boolean on):设置线程为守护线程(当参数为 true 时)。守护线程是为其他线程服务的,当所有非守护线程执行完毕后,守护线程会自动结束。

MyThread thread1 = new MyThread("飞机"); // 非守护线程

MyThread2 thread2 = new MyThread2("坦克"); // 守护线程

thread2.setDaemon(true);

thread1.start();

thread2.start(); // 当thread1执行完毕后,thread2会陆续结束

6、线程礼让public static void yield():出让当前线程的 CPU 执行权,让其他线程有机会执行,但当前线程仍可能再次获取 CPU 资源。

@Override

public void run() {

for (int i = 0; i < 10; i++) {

System.out.println(getName() + "hello" + i);

Thread.yield(); // 出让CPU执行权

}

}

7、线程插队public final void join():让调用该方法的线程插入到当前线程之前执行,当前线程会等待插入的线程执行完毕后再继续执行。

public class Main {

public static void main(String[] args) throws InterruptedException {

MyThread thread1 = new MyThread("飞机");

thread1.start();

thread1.join(); // 让thread1插入到main线程之前执行

// main线程会等待thread1执行完毕后再执行以下循环

for (int i = 0; i < 10; i++) {

System.out.println("main" + i);

}

}

}

通过上述方法的灵活使用,我们可以有效地控制线程的执行流程,实现多线程之间的协作与同步,满足不同场景下的并发需求。

Copyright © 2088 波隆网游活动中心 - 热门游戏限时福利聚合站 All Rights Reserved.
友情链接