1.在Java中,如果要实现多线程,那么就必须依靠一个线层的主体类,但是这个主体类在定义的时候也需要一些特殊的要求,这个类可以继承Thread类,实现Runable接口或实现Callable接口来完成定义。
1.1 Thread类实现多线程
MyThread.java
class MyThread extends Thread { private String title; public MyThread(String title) { this.title=title; } //任何继承了Thread类的线程主体类就是一个线程的主类,同时线程类中需要明确复写父类的run()方法 @Override public void run() { //线程逻辑代码 for(int i=0;i<10;i++) { System.out.println(this.title+"运行"+i+"次"); } } }
test.Java
public class Test { public static void main(String[] args) { new MyThread("线程A").start(); new MyThread("线程B").start();; new MyThread("线程C").start(); } }
多线程之间彼此交替执行,但是每次的执行结果肯定是不一样的。要先启动线程就必须依靠Thread类的start()方法,线程启动之后会默认调用run()方法。
面试题1:为什么线程启动的时候必须调用start()方法而不是直接调用run()方法呢?
Thread类源码:
public synchronized void start() { if (threadStatus != 0) throw new IllegalThreadStateException(); group.add(this); boolean started = false; try { start0();//private native void start0(); started = true; } finally { try { if (!started) { group.threadStartFailed(this); } } catch (Throwable ignore) { } } }
调用start()方法后会继承调用start0()方法,调用被Native关键字修饰的start0()方法,而native关键字会是指Java本地接口调用,即使用本地系统的函数功能完成,多线程的实现需要操作系统的支持,start0()方法没有方法体
而把这个方法体直接交给Jvm去实现,Jvm通过调度算法调用本地系统的函数功能完成。而直接调用run()方法只是普通的方法调用并不能实现多线程。
2.Runable接口实现多线程
面向对象的程序设计通过实现标准定义与解耦操作,所以多线程又提供了Runable接口实现多线程开发。
Runable.java
@FunctionalInterface public interface Runnable { public abstract void run();
}
一旦实现Runable接口则MyThread类中就不再有start()方法,这时候要启动线程需要利用Thread的构造方法,向其中传入Runable的实现对象
public class MyRunnable implements Runnable{ private String ThreadName; public MyRunnable(String ThreadName) { this.ThreadName=ThreadName; } @Override public void run() { for(int i=0;i<10;i++) { System.out.println(this.ThreadName+"运行"+i+"次"); } } }
public class Test { public static void main(String[] args) { Thread threadA=new Thread(new MyRunnable("A")); Thread threadB=new Thread(new MyRunnable("B")); Thread threadC=new Thread(new MyRunnable("C")); threadA.start(); threadB.start(); threadC.start(); } }
2.1Thread类与Runnable实现多线程的区别’
Thread.java
public class Thread implements Runnable { //内容}
Runnable.java
@FunctionalInterface public interface Runnable { public abstract void run(); }
Thread类是Runnable的实现类,Runable是一个父类接口,所以之间继承Thread类实际上还是复写了Runnable接口的Run()方法,两者都可以实现完全相同的效果,如果直接继承Thread类,那么资源本身就是一个线程对象了。
3.Callable接口实现多线程
Java针对多线程执行完毕后不返回信息的缺陷,提供了Callable接口。
public class MyCallable implements Callable<String>{ //定义时设置一个泛型,此泛型的类型就是返回数据的类型 @Override public String call() throws Exception { for(int i=0;i<10;i++) { System.out.println("线程执行!"); } return "结果"; } }
3.1 callable接口与FutureTask类的关系
FutureTask<String> task=new FutureTask<>(new MyCallable()); new Thread(task).start(); System.out.println("线程返回的结果"+task.get());