创建线程的三种方式:
1、实现Runnable接口
通过实现Runnable接口创建并启动线程一般步骤如下:
(1)、定义Runnable接口的实现类,一样要重写run()方法,这个run()方法和Thread中的run()方法一样是线程的执行体
(2)、创建Runnable实现类的实例,并用这个实例作为Thread的target来创建Thread对象,这个Thread对象才是真正的线程对象
(3)、第三部依然是通过调用线程对象的start()方法来启动线程
public class RunnableThreadGY1803 implements Runnable {
@Override
public void run() {
}
public static void main(String[] args) {
RunnableThreadGY1803 threadGY1803 = new RunnableThreadGY1803();
Thread thread = new Thread(threadGY1803);
thread.start();
}
}
2、继承Thread类创建线程
(1)、定义Thread类的子类,并重写该类的run()方法,该方法的方法体就是线程需要完成的任务,run()方法也称为线程执行体。
(2)、创建Thread子类的实例,也就是创建了线程对象
(3)、启动线程,即调用线程的start()方法
public class ThreadGY1803 extends Thread{
@Override
public void run() {
}
public static void main(String[] args) {
ThreadGY1803 C = new ThreadGY1803();
C.setName("C");
}
3、实现Callable接口
(1)、callable接口的实现他是一种线程池提供的创建线程的方式
(2)、实现callable接口,并实现call方法
(3)、创建线程池( Executors提供的方法创建线程池)
(4)、创建callable的实例
(5)、 将实例的对象通过线程池的sumbit方法提交给线程
public class CallableDY1803 implements Callable{
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
CallableDY1803 task = new CallableDY1803();
Future<Integer> future = executorService.submit(task);
executorService.shutdown();
System.out.println("主线程执行任务");
try {
Thread.sleep(3000);
}catch (InterruptedException e){
e.printStackTrace();
}
try {
System.out.println("task运行结果:"+future.get());
}catch (InterruptedException e){
e.printStackTrace();
}catch (ExecutionException e){
e.printStackTrace();
}
System.out.println("所有任务执行完毕");
}
@Override
public Object call() throws Exception {
System.out.println("子线程执行任务");
Thread.sleep(5000);
return 1000;
}
}
三种线程创建多线程的比较:
实现Runnable和实现Callable接口的方式基本相同,不过是后者执行call()方法有返回值,后者线程执行体run()方法无返回值,因此可以把这两种方式归为一种这种方式与继承Thread类的方法之间的差别如下:
1、线程只是实现Runnable或实现Callable接口,还可以继承其他类。
2、这种方式下,多个线程可以共享一个target对象,非常适合多线程处理同一份资源的情形。
3、但是编程稍微复杂,如果需要访问当前线程,必须调用Thread.currentThread()方法。
4、继承Thread类的线程类不能再继承其他父类(Java单继承决定)。