最近在看《JAVA并发编程实战》这本书,以前对创建一个线程来执行任务都是比较混乱的,思路不清晰,而且写代码的时候也无从下手。
在阅读这本书的过程中,逐渐对线程这个概念愈发清晰,于是今天整理一下如何创建线程来完成任务。
在网上众多博客以及面试题中,都会提到使用线程的4种方式
1. 通过继承Thread
2. 通过实现Runnable
3. 通过Callable+FutureTask
4. 通过线程池
这样的说法虽说有些不严谨,但是以现在我的知识储备还不能完全的指出到底哪里不严谨,跑偏了。
首先是第1种,通过继承Thread来创建线程
Thread类就是线程在java中的形象。创建一个Thread并启动就相当于开启了一个线程,而线程做的任务就是Thread类里的run()方法,因此我们需要重写这个run()方法用于完成我们想要做的任务
所以该方法是让一个类A继承Thread,并且重写它的run()方法。
创建一个线程并启动的写法通常是new Thread().start();
因为类A继承了Thread,所以写法变成了new A().start();
示例如下
public class ThreadExample { @Test public void example1(){ System.out.println("这是主线程"+Thread.currentThread().getName()); //创建一个线程并且启动 new A("A").start(); } /** * 通过继承Thread并且重写run()方法来使用线程完成任务 */ public class A extends Thread{ public A(String name) { super(name); } @Override public void run() { System.out.println("这是一个新的线程"+Thread.currentThread().getName()); } } }
接着是第2种方法,通过实现Runnable接口来使用线程
Thread类有一个构造器,其形参为Runnable类,既然是作为一个参数传入,那其实就存在两种方式
①就是通过类B实现Runnable接口并重写run()方法,然后将类B的实例作为参数传入
②创建一个Runnable的匿名内部类传入(这种方法有个好处就是,线程中执行任务的类可以不用implements Runnable接口,直接在匿名内部类的重写run方法中调用执行任务类的方法即可完成任务)
以下是两种实现方式的代码
public class ThreadExample { @Test public void example2(){ System.out.println("这是主线程,"+Thread.currentThread().getName()); //创建一个线程并传入B的实例对象 new Thread(new B(),"B").start(); } /** * 方式①:通过实现Runnable接口的方式实现 */ private class B implements Runnable{ @Override public void run() { System.out.println("这是一个新线程"+Thread.currentThread().getName()); } } }
public class ThreadExample { @Test public void example3(){ System.out.println("这是主线程,"+Thread.currentThread().getName()); /** * 方式②:通过传入一个Runnable匿名内部类来实现 */ new Thread(new Runnable() { @Override public void run() { System.out.println("这是一个新线程"+Thread.currentThread().getName()); } },"B").start(); } }
第3种方法和第4种方法后期再补充