Java 实现多线程的几种方式
Java 多线程的实现方式有:继承Thread类,实现Runnable接口。另外,使用内部类实现,Callable、Future组合实现(有返回值),使用线程池,定时器以及Java 8中Lambda表达式实现的方式,实际是对前两种方式的变形。
一、继承Thread类
继承Thread类,重写run()方法,Thread类也是Runnable接口的一个实现,启动线程的唯一方法是start()方法。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19package Thread;
public class ThreadDemo extends Thread {
public void run() {
System.out.println("当前线程为:" + Thread.currentThread().getName());
}
public static void main(String[] args) {
ThreadDemo demo1 = new ThreadDemo();
ThreadDemo demo2 = new ThreadDemo();
demo1.start();
demo2.start();
}
}
程序运行结果为:1
2当前线程为:Thread-0
当前线程为:Thread-1
二、实现Runnable接口
实现Runnable接口,重写run()方法,为了启动Runnable实例,需要实例化一个Thread1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21package Thread;
public class RunnableDemo implements Runnable {
public static void main(String[] args) {
RunnableDemo demo = new RunnableDemo();
Thread thread1 = new Thread(demo);
Thread thread2 = new Thread(demo);
thread1.start();
thread2.start();
}
public void run() {
System.out.println("当前线程为:" + Thread.currentThread().getName());
}
}
程序运行结果为:1
2当前线程为:Thread-1
当前线程为:Thread-0
三、使用内部类实现
如果一个线程只执行一次,使用上述两种方法就显得有些麻烦,使用内部类正好解决这种情况。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29package Thread;
public class InnerThreadDemo {
public static void main(String[] args) {
// 继承Thread类
new Thread() {
public void run() {
System.out.println("继承Thread线程");
}
}.start();
// 实现Runnable接口
new Thread(new Runnable() {
public void run() {
System.out.println("实现Runnable线程");
}
}).start();
}
}
程序运行结果为:1
2继承Thread线程
实现Runnable线程
四、使用Callable、Future组合
实现Runnable、继承Thread类是没有返回结果的,此时需要用Callable和Future组合实现有返回值的线程。
1、使用匿名内部类实现Callable接口,重写call()方法。
2、实例化一个FutureTask,指定Callable实例,作为线程任务。
3、使用Thread开启线程任务。
4、使用FutureTask的get()方法获取线程的执行结果。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37package Thread;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class CallableDemo {
static Callable<Integer> num = new Callable<Integer>() {
public Integer call() throws Exception {
return 1;
}
};
static Callable<String> str = new Callable<String>() {
public String call() throws Exception {
return "str";
}
};
public static void main(String[] args) throws Exception {
FutureTask<Integer> number = new FutureTask<Integer>(num);
FutureTask<String> sub = new FutureTask<String>(str);
new Thread(number).start();
new Thread(sub).start();
System.out.println("Integer执行结果为:" + number.get());
System.out.println("String执行结果为:" + sub.get());
}
}
程序输出结果为:1
2Integer执行结果为:1
String执行结果为:str
注意:get()方法是阻塞的,如果线程没有返回值,则get()方法一直等待
五、使用线程池
Java通过Executors提供了四种线程池,分别为:
1、newSingleThreadExecutor: 初始化的线程池中只有一个线程,唯一的线程可以保证所有提交的任务按照指定顺序执行。
2、newFixedThreadPool:创建一个固定数量线程池,可控制线程最大并发数,超出的线程会在队列中等待。
3、newScheduledThreadPool:创建一个固定数量线程池,支持定时及周期性任务执行。
4、newCachedThreadPool:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
使用线程池:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48package Thread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
public class ExecutorDemo {
static Callable<Integer> num = new Callable<Integer>() {
public Integer call() throws Exception {
return 1;
}
};
static Callable<String> str = new Callable<String>() {
public String call() throws Exception {
return "str";
}
};
public static void main(String[] args) throws Exception {
FutureTask<Integer> number = new FutureTask<Integer>(num);
FutureTask<String> sub = new FutureTask<String>(str);
ExecutorService threadPool = Executors.newFixedThreadPool(2);
try {
// 给线程中加入任务
threadPool.execute(number);
threadPool.execute(sub);
} finally {
// 关闭线程池
threadPool.shutdown();
}
System.out.println("Integer执行结果为:" + number.get());
System.out.println("String执行结果为:" + sub.get());
}
}
程序执行结果为:1
2Integer执行结果为:1
String执行结果为:str
推荐大家阅读:(https://www.cnblogs.com/dolphin0520/p/3932921.html)
六、使用定时器
定时计划任务功能在Java中主要使用的就是Timer对象,它在内部使用多线程的方式进行处理
1、实例化Timer,执行schedule()方法。
2、实例化TimerTask,重写run()方法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34package Thread;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TimerDemo {
public static void main(String[] args) {
Timer timer = new Timer();
// 每隔5秒执行
timer.schedule(new TimerTask() {
public void run() {
System.out.println("每隔5秒执行一次");
}
}, new Date(), 5000);
// 固定时间执行
timer.schedule(new TimerTask() {
public void run() {
System.out.println("固定时间执行");
}
}, new Date());
}
}
程序运行结果为:1
2
3
4
5
6
7
8每隔5秒执行一次
固定时间执行
每隔5秒执行一次
每隔5秒执行一次
每隔5秒执行一次
每隔5秒执行一次
每隔5秒执行一次
...
schedule()还有好多重载方法,可以查看相应的API进行了解。
七、使用Lambda表达式实现
1 | package Thread; |
程序运行结果为:1
2
3主线程为:main
Runnable线程为:Thread-0
Thread线程为:Thread-1