目录
概述
继承Thread类:
实现Runnable接口:
实现Callable接口:
示例代码
继承Thread类示例
实现Runnable接口示例
实现Callable接口示例
调用三种线程测试示例
线程常用的成员方法
概述
常见的创建线程的方式包括:继承Thread类、实现Runnable接口和实现Callable接口。
-
继承Thread类:
- 这种方式是通过创建一个类,继承自Thread类,并重写其run()方法来定义线程执行的任务。
- 优点:简单易用,适合简单的线程任务。
- 缺点:Java不支持多重继承,因此如果继承Thread类,则无法继承其他类。
-
实现Runnable接口:
- 这种方式是创建一个类,实现Runnable接口,并实现其run()方法来定义线程执行的任务。
- 优点:避免了Java单继承的限制,使得代码更加灵活。
- 缺点:稍微复杂一些,需要创建Thread对象并将实现了Runnable接口的对象作为参数传递给Thread对象。
-
实现Callable接口:
- 实现
Callable
接口,并实现call()
方法。call()
方法是在新线程中执行的任务,它可以返回一个结果。 - 返回结果:
Callable
接口的call()
方法可以返回一个结果,而Runnable
接口的run()
方法是void
类型的,无法返回结果。 - 抛出异常:
call()
方法可以抛出异常,而run()
方法不能。 - Future对象:
Callable
接口执行后可以通过Future
对象获取结果,而Runnable
接口无法获取执行结果。 - 泛型支持:
Callable
接口支持泛型,可以指定call()
方法的返回类型。
- 实现
示例代码
继承Thread类示例
public class ThreadTest extends Thread{
/*
* 第一种多线程实现方式
* 继承 Thread 类
* 然后重写run方法
* */
@Override
public void run() {
for (int i = 0; i < 100; i++) {
//循环打印消息,getName方法为当前线程名称
System.out.println(getName()+"线程运行");
}
}
}
实现Runnable接口示例
public class RunnableTest implements Runnable {
/**
* 第二种多线程实现方式
* 此方法是Runnable接口所要求实现的方法,它定义了当线程启动后将要执行的任务逻辑。
* 在本例中,线程将循环打印100次当前线程的名字和消息"线程运行"。
*/
@Override
public void run() {
// 循环100次
for (int i = 0; i < 100; i++) {
// 打印当前线程的名字和消息"线程运行"
System.out.println(Thread.currentThread().getName() + "线程运行");
}
}
}
实现Callable接口示例
/**
* @author :枫夜
* @date : 2024-04-22 16:36
* @description : 本类实现了Callable接口,用于定义一个可被线程执行的任务,并返回计算结果。
* 本例中,任务计算从0到99的整数之和,并返回结果。
**/
public class CallableTest implements Callable<Integer> {
/**
* 此方法是Callable接口所要求实现的方法,它定义了当线程启动后将要执行的任务逻辑。
* 在本例中,线程将计算从0到99的整数之和,并返回结果。
* 使用Callable实现创建的线程,可以获取到线程的返回值
*
* @return 计算得到的整数之和
* @throws Exception 如果在计算过程中发生异常,可抛出Exception以传递给调用者
*/
@Override
public Integer call() throws Exception {
// 初始化累加器
int sum = 0;
// 循环计算从0到99的整数之和
for (int i = 0; i < 100; i++) {
sum += i;
}
// 返回计算结果
return sum;
}
}
调用三种线程测试示例
public class Test01 {
/**
* 此方法用于展示创建并启动两个自定义线程对象的过程。
* 它使用TestNG的@Test注解标记为一个测试用例。
*/
@Test
public void Test01() {
// 创建两个ThreadTest实例,分别命名为"线程1"和"线程2"
ThreadTest threadTest1 = new ThreadTest();
ThreadTest threadTest2 = new ThreadTest();
// 设置线程1的名字为"线程1"
threadTest1.setName("线程1");
// 设置线程2的名字为"线程2"
threadTest2.setName("线程2");
// 启动线程1,使其进入就绪状态并等待CPU调度执行
threadTest1.start();
// 启动线程2,使其进入就绪状态并等待CPU调度执行
threadTest2.start();
}
/**
* 此方法用于展示使用同一个Runnable实例创建并启动两个线程的过程。
* 它使用TestNG的@Test注解标记为一个测试用例。
*/
@Test
public void test02() {
// 创建一个RunnableTest实例,作为线程共享的任务对象
RunnableTest runnableTest = new RunnableTest();
// 使用RunnableTest实例创建线程1
Thread thread1 = new Thread(runnableTest);
// 使用RunnableTest实例创建线程2
Thread thread2 = new Thread(runnableTest);
// 设置线程1的名字为"线程1"
thread1.setName("线程1");
// 设置线程2的名字为"线程2"
thread2.setName("线程2");
// 启动线程1,使其进入就绪状态并等待CPU调度执行
thread1.start();
// 启动线程2,使其进入就绪状态并等待CPU调度执行
thread2.start();
}
/**
* 此方法用于展示使用Callable创建一个线程并获取其计算结果的过程。
* 它使用TestNG的@Test注解标记为一个测试用例,并声明抛出可能发生的ExecutionException和InterruptedException。
*/
@Test
public void test03() throws ExecutionException, InterruptedException {
// 创建一个CallableTest实例,用于计算从0到99的整数之和
CallableTest callableTest = new CallableTest();
// 使用CallableTest实例创建一个FutureTask,以便获取计算结果
FutureTask<Integer> integerFutureTask = new FutureTask<>(callableTest);
// 创建一个线程来执行FutureTask
Thread thread = new Thread(integerFutureTask);
// 启动线程,开始执行Callable任务
thread.start();
// 调用FutureTask的get方法,阻塞等待直到计算结果可用,并返回结果
Integer integer = integerFutureTask.get();
// 输出计算结果
System.out.println(integer);
}
}
线程常用的成员方法
-
String getName()
:- 返回当前线程的名称。
- 示例:
String threadName = Thread.currentThread().getName();
-
void setName(String name)
:- 设置当前线程的名称。
- 示例:
Thread.currentThread().setName("MyThread");
-
static Thread currentThread()
:- 返回当前正在执行的线程对象。
- 示例:
Thread currentThread = Thread.currentThread();
-
static void sleep(long time)
:- 使当前线程休眠指定的时间(以毫秒为单位)。
- 示例:
Thread.sleep(1000);
-
void setPriority(int newPriority)
:- 设置当前线程的优先级,范围为1(最低)到10(最高),默认是5。
- 示例:
Thread.currentThread().setPriority(5);
-
final int getPriority()
:- 返回当前线程的优先级。
- 示例:
int priority = Thread.currentThread().getPriority();
-
final void setDaemon(boolean on)
:- 将当前线程设置为守护线程(Daemon Thread)或用户线程。
- 守护线程在用户线程结束时自动销毁,销毁不是直接销毁,每次时间不同,但不会时间太长。
- 示例:
Thread.currentThread().setDaemon(true);
-
public static void yield()
:- 暂停当前正在执行的线程对象,并允许其他线程执行。这个方法的作用是让出当前线程的执行权给其他线程,出让之后重新抢夺执行权,谁抢到执行权谁就执行。
- 示例:
Thread.yield();
-
public static void join()
:- 当前线程停止运行,直到被调用的线程执行完毕,然后当前线程再运行。
- 示例:
thread.join();这个示例写在那个线程中,就暂停当前线程,然后运行thread这个线程。