Java官方创建线程的两种方式
Java源码中其实明确写了创建线程只有两种方式
我们通过源码可以得知,有两种方法创建线程。一个是继承Thread类,一个是实现Runnable,但很多开发者会将Callable和使用线程池创建也算成创建线程的方式。
继承Thread类
代码示例:
public class Main {
public static void main(String[] args) {
extendThread();
}
//继承Thread类
private static void extendThread(){
Thread t1 = new Thread(){
@Override
public void run() {
super.run();
for (int i = 0; i < 10; i++) {
System.out.println("线程:" + i);
}
}
};
}
}
实现Runnable的run方法
public class MyRunnable implements Runnable{
private Integer ticket = 10;
@Override
public void run() {
while(this.ticket > 0) {
synchronized (this) {
System.out.println(Thread.currentThread().getName()+":"+this.ticket);
this.ticket--;
}
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
new Thread(myRunnable,"线程1").start();
new Thread(myRunnable,"线程2").start();
}
}
其余两种创建线程的方式
实现Callable的call方法
public class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
Integer sum = 0;
for (int i = 0; i < 10; i++) {
sum += i;
}
return sum;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyCallable myCallable = new MyCallable();
FutureTask<Integer> futureTask = new FutureTask<>(myCallable);
Thread t1 = new Thread(futureTask,"线程1");
t1.start();
System.out.println(futureTask.get());
}
}
使用线程池实现
public class MyThreadPool {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService es = Executors.newFixedThreadPool(5);
FutureTask<Integer> f = new FutureTask<>(() -> {
Integer sum = 0;
for (int i = 0; i < 10; i++) {
sum += i;
}
return sum;
});
es.submit(f);
System.out.println(f.get());
}
}
区别对比
几种创建线程方式的对比:
实现Runnable和实现Callable接口方式基本相同,不过是后者执行call方法并且有返回值,而run方法无任何返回值,因此可以把这两种方式归为一种方式与继承Thread类的方式进行对比,差别如下(以实现接口方式为主):
1.线程只是实现Runnable接口或Callable接口,还可以继承其他类(有点像接口和抽象类的区别,java是单继承的,但可以实现多个接口)
2.实现接口的方式多个线程可以共享一个target对象,非常适合多线程处理同一份资源的情形
3.如果需要访问当前线程,必须调用Thread.currentThread方法
4.继承Thread类的线程类不能再继承其他父类(java单继承决定)