之前有去好好了解了线程这块的原理,过了段时间有点点忘了,现在写下来回忆回忆
线程的四种实现方法:
1.继承Thread类,重写run方法
2.实现Runnable接口,实现run方法
3.实现Callable接口,实现call方法
4.使用ExecutorService线程池的方式创建线程
继承Thread类,重写run方法
package com.example.test;
public class Test extends Thread {
@Override
public void run() {
System.out.println("这是继承了Thread类的线程");
}
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
Test test = new Test();
test.start();
}
}
}
实现Runnable接口,实现run方法,需要Thread类进行封装
package com.example.test;
public class Test implements Runnable {
@Override
public void run() {
System.out.println("这是实现Runnable接口的线程");
}
public static void main(String[] args) {
for (int i =0; i <5; i++) {
Test test =new Test();
Thread thread =new Thread(test);
thread.start();
}
}
}
实现Callable接口,实现call方法,call方法有返回参,需要FutureTask,Thread类进行封装,用FutureTask对象使用get()获取返回参
package com.example.test;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Test implements Callable {
@Override
public Object call() {
System.out.println("这是实现Callable接口的线程");
return "Hello World!";
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
for (int i = 0; i < 5; i++) {
Callable test = new Test();
FutureTask futureTask = new FutureTask<>(test);
Thread thread = new Thread(futureTask);
thread.start();
Object a = futureTask.get();
System.out.println(a);
}
}
}
使用ExecutorService线程池的方式创建线程,当调用submit的时候,会把Callable对象传递进去初始化一个FutureTask对象,然后调用execute方法。而FutureTask已有实现好的run方法。run方法中调用了call()方法。当submit传入的是Runnable对象时候,把Runnable经过转换变成FutureTask对象,然后调用execute方法。FutureTask已有实现好的run方法,run方法中调用了call()方法,call()方法在调用Runnable对象的run方法。submit有返回值,而execute没有。使用ExecutorService线程池一定要记得shutDown(), 当线程池调用该方法时,线程池的状态则立刻变成SHUTDOWN状态。此时,则不能再往线程池中添加任何任务,否则将会抛出RejectedExecutionException异常。但是,此时线程池不会立刻退出,直到添加到线程池中的任务都已经处理完成,才会退出
package com.example.test;
import java.util.concurrent.*;
public class Test implements Runnable {
@Override
public void run() {
System.out.println("这是实现Runnable接口的线程");
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
Test test = new Test();
Thread thread = new Thread(test);
Future future = executorService.submit(thread);
// executorService.execute(test);
if (future.get() == null) {
System.out.println("任务完成");
}
}
executorService.shutdown();
}
}
最后说一点,在不使用线程池的情况下,使用线程最好是实现Runnable接口或者Callable接口,因为继承Thread类,线程是无法实现复用的,只能新建线程。实现Runnable接口或者Callable接口,就可以实现线程复用,大大减少线程产生,要知道线程是很珍贵的,是会占用资源的