赞
踩
创建多线程常用的方法有四种,继承Thread、实现Runnable接口、使用Callable和FutureTask和线程池
创建一个多线程需要执行两个步骤
代码实现如下:
public class MultiThread1 {
private static final int MAX_TURN = 5;
public static String getCurrentThread() {
return Thread.currentThread().getName();
}
static class CreateThread extends Thread {
@Override
public void run() {
for (int i = 0; i < MAX_TURN; i++) {
System.out.println("线程名称为:" + getCurrentThread());
}
System.out.println("线程名称为:" + getCurrentThread() + "运行结束");
}
}
public static void main(String[] args) {
Thread thread = null;
for (int i = 0; i < 2; i++) {
thread = new CreateThread();
thread.start();
}
System.out.println("线程名称为:" + getCurrentThread() + "运行结束");
}
}
将需要异步执行的业务逻辑代码写在Runnable实现类的run()方法中,再将Runnable实例作为target执行目标传入Thread实例,其完整步骤如下:
具体代码如下:
public class MultiThread2 {
private static final int MAX_TURN = 5;
public static String getCurrentThread() {
return Thread.currentThread().getName();
}
static class CreateThread implements Runnable {
@Override
public void run() {
for (int i = 0; i < MAX_TURN; i++) {
System.out.println("当前线程名称为:" + getCurrentThread());
}
System.out.println("当前线程名称为:" + getCurrentThread() + "运行结束");
}
}
public static void main(String[] args) {
Thread thread = null;
for (int i = 0; i < 2; i++) {
Runnable runnable = new CreateThread();
thread = new Thread(runnable);
thread.start();
}
}
}
使用Runnable创建线程目标类还有两种方法
如果target实现类是一次性类,可以使用匿名实例,代码如下:
public class MultiThread3 {
private static final int MAX_TURN = 5;
static int threadNo = 1;
public static void main(String[] args) {
Thread thread = null;
for (int i = 0; i < 2; i++) {
thread = new Thread(new Runnable() {
@Override
public void run() {
for (int j = 0; j < MAX_TURN; j++) {
System.out.println("多线程执行,第:" + j + "次执行!");
}
System.out.println("运行结束");
}
}, "RunnableThread" + threadNo++);
thread.start();
}
System.out.println("运行结束");
}
}
Runnable接口是一个函数式接口,在接口实现时可以使用Lambda表达式提供匿名实现,其代码实现如下:
public class MultiThread4 {
private static final int MAX_TURN = 5;
private static int threadNo = 1;
public static void main(String[] args) {
Thread thread = null;
for (int i = 0; i < 2; i++) {
thread = new Thread(() -> {
for (int j = 0; j < MAX_TURN; j++) {
System.out.println("多线程执行,第:" + j + "次执行!");
}
System.out.println("多线程运行结束");
}, "RunnableThread" + threadNo++);
thread.start();
}
System.out.println("多线程运行结束");
}
}
缺点
优点
需要获取异步执行的返回结果时,使用Callable和FutureTask创建多线程
使用Callable和FutureTask创建线程的步骤如下:
代码实现如下:
public class MultiThread5 {
private static final int COMPUTE_TIMES = 100000000;
static class CreateThread implements Callable<Long> {
@Override
public Long call() throws Exception {
long startTime = System.currentTimeMillis();
System.out.println("多线程执行开始,当前时间为:" + startTime);
Thread.sleep(1000);
for (int i = 0; i < COMPUTE_TIMES; i++) {
int j = i * 10000;
}
long endTime = System.currentTimeMillis();
System.out.println("多线程执行结束,当前时间为:" + endTime);
long used = endTime - startTime;
System.out.println("多线程执行结束,使用时间为:" + used);
return used;
}
}
public static void main(String[] args) throws InterruptedException {
CreateThread createThread = new CreateThread();
FutureTask<Long> futureTask = new FutureTask<>(createThread);
Thread thread = new Thread(futureTask, "returnThread");
thread.start();
System.out.println("获取多线程执行结果");
try {
System.out.println(thread.getName() + "线程占用时间:" + futureTask.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("多线程执行结束");
}
}
前面几种方法创建的Thread实例在执行完成之后是不可复用的,实际工作中需要对已创建好的线程实例进行复用,需要用到线程池。
ExecutorService是Java提供的一个线程池接口,每次在异步执行target目标任务的时候,可以通过ExecutorService线程池实例去提交或者执行。ExecutorService实例负责对池中的线程进行管理和调度,并且可以有效控制最大并发线程数,提高系统资源的使用率,同时提供定时执行、定频执行、单线程、并发数控制等功能
代码实现如下:
public class MultiThread6 {
private static final int MAX_TURN = 5;
private static final int COMPUTE_TIMES = 100000000;
private static ExecutorService pool = Executors.newFixedThreadPool(3);
static class RunnableTask implements Runnable {
@Override
public void run() {
for (int i = 0; i < MAX_TURN; i++) {
System.out.println("多线程执行,第:" + i + "次执行");
}
}
}
static class CallableTask implements Callable<Long> {
@Override
public Long call() throws Exception {
long startTime = System.currentTimeMillis();
System.out.println("多线程执行,开始时间为:" + startTime);
Thread.sleep(1000);
for (int i = 0; i < COMPUTE_TIMES; i++) {
int j = i * 10000;
}
long endTime = System.currentTimeMillis();
long used = startTime - endTime;
System.out.println("多线程执行结束,用时:" + used);
return used;
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
pool.execute(new RunnableTask());
pool.execute(new Runnable() {
@Override
public void run() {
for (int i = 0; i < MAX_TURN; i++) {
System.out.println("多线程执行,直接实现Runnable");
}
}
});
Future<Long> future = pool.submit(new CallableTask());
Long result = future.get();
System.out.println("异步执行多线程结果为:" + result);
}
}
注意:实际开发中不会使用Executors创建线程池,而是使用ThreadPoolExecutor的构造方法
接收的参数不一样
submit()可以接收两种入参:无返回值的Runnable类型的target执行目标实例和有返回值的Callable类型的target执行目标实例,execute()只接收无返回值的target执行目标实例或者无返回值的Thread实例
submit()有返回值,execute()没有返回值
submit()方法在提交异步target执行目标之后会返回Future异步任务实例,以便对target的异步执行过程进行控制,比如取消执行、获取结果等。execute()没有任何返回,target执行目标实例在执行之后没有办法对其异步执行过程进行控制,只能任其执行,直到其执行结束
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。