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());