- 继承Thread类
Thread类本质上实现了Runnable接口的一个实例,代表了一个线程的实例,启动线程的唯一方法就是通过Thread的start()实例方法。start()是一个native方法,他启动一个新线程,并执行run()方法。
public class KobeThreadTest extends Thread {
@Override
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println("鸡你太美:" + i);
}
}
public static void main(String[] args) {
KobeThreadTest kobeThreadTest = new KobeThreadTest();
kobeThreadTest.start();
}
}
2.实现Runnable接口
如果自己的类已经exteds另一个类,那么无法继承Thread类,此时可以实现Runnable接口。
public class KobeRunnableTest implements Runnable{
@Override
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println("鸡你太美:" + i);
}
}
public static void main(String[] args) {
KobeRunnableTest kobeRunnableTest=new KobeRunnableTest();
Thread thread=new Thread(kobeRunnableTest);
thread.start();
}
}
- 使用Callable有返回值的线程
使用callable创建线程能够返回线程数据,与Runnable接口类似,也需要通过创建Thread类来创建线程。callable任务后可以获得一个FutureTask对象,调用该对象的.get()方法就可以获取到callable任务的返回值。
public class KobeCallableTest implements Callable {
@Override
public Object call() {
for (int i = 0; i < 50; i++) {
System.out.println("鸡你太美:" + i);
}
return "收到律师函";
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
KobeCallableTest kobeCallableTest = new KobeCallableTest();
FutureTask futureTask = new FutureTask(kobeCallableTest);
Thread thread = new Thread(futureTask);
thread.start();
//拿到线程的返回值
System.out.println(futureTask.get());
}
}
- 使用ThrealPool线程池
线程和数据库连接这些资源都很宝贵,每次创建和销毁造成不必要的资源消耗,那么我们可以使用缓存的策略来创建,那就是使用到了线程池。Java线程池的顶级接口是Executor,但是严格意义上Executor并不是一个线程池,而是一个执行线程的工具,真正的线程池接口是ExecutorService
public class KobeThreadPoolTest {
public static void main(String[] args) {
ExecutorService executorService=Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println(Thread.currentThread().getName() + "鸡你太美:" + i);
}
}
});
}
executorService.shutdown();
}
}
总结:
- Runnable和Callable接口实现方式适合多个线程进行资源共享。因为继承Thread属于Java中的单一继承,接口则可以多实现,提高了扩展性。线程池中只能使用接口实现,不能直接继承Thread实现。
- Runnable重写的是run()方法,没有返回值,并且不可抛出异常。
- Callable重写的是call()方法,可以有返回值,可以抛出异常,并且可以通过Future对象可以了解任务的执行情况。
- 使用线程池创建可以避免资源过度消耗,提升效率。