实现多线程的两种方式
- 实现Runnable接口
- 继承Thread类
public class RunableStyle implements Runnable{
public static void main(String[] args) {
Thread thread = new Thread(new RunableStyle());
thread.start();
}
@Override
public void run() {
System.out.println("用Runnable实现线程");
}
}
public class ThreadStyle extends Thread {
public static void main(String[] args) {
new ThreadStyle().start();
}
@Override
public void run() {
System.out.println("用Thread实现线程创建");
}
}
使用Runnable更好,为什么呢?
- 从代码架构考虑,run方法应该跟Thread解耦,这样更好
- 如果继承Thread类,每次想新建任务只能新建一个线程,新建一个线程的消耗是特别大的;用Runnable在后续可以使用线程池之类的工具,就可以减少很大的开销
- 由于Java无法双继承,导致这个类就无法继承其他类,限制了可扩展性
两种方法的本质:
Runable:最终调用target.run()
Thread:run()整个被重写
在Runable里他就是会将run的方法传入,根据下面的判断;
但是Thread里就是直接覆盖了run方法,不会去判断target是否为空
private Runnable target;
@Override
public void run() {
if (target != null) {
target.run();
}
}
同时使用Runnable和Thread
public class BothRunnableThread {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("我是Runnable");
}
}) {
@Override
public void run() {
System.out.println("我是Thread");
}
}.start();
}
}
输出
我是Thread
why
这是因为在Thread里的run方法已经直接覆盖了runnable中的run方法,所以即使在上面我们传入了runnable的run方法也是没用的,因为Thread已经覆盖了,只会执行Thread中的run方法
准确的说创建线程只有一种方式那就是构造Thread类,而实现线程的执行单元有两种方式,就是实现Runnable的run方法和重写Thread的run方法
以下方式创建的线程其实并非和上面两种不同,在本质上其实就是上面两种方式的包装
使用线程池创建线程
public class ThreadPool {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 1000; i++) {
executorService.submit(new Task(){
});
}
}
}
class Task implements Runnable {
@Override
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
}
}
定时器创建线程
public class TimmerTask {
public static void main(String[] args) {
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}, 1000, 1000);
}
}
匿名内部类创建
public class AnonymousinnerClass {
public static void main(String[] args) {
new Thread() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}.start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}).start();
}
}
Lambda创建
public class Lambda {
public static void main(String[] args) {
new Thread(() -> System.out.println(Thread.currentThread().getName())).start();
}
}