Java语言内置了多线程支持。当咱们启动一个Java程序时,其实是启动了一个JVM进程,而后JVM启动主线程来执行main()
方法。在main()
方法中,咱们又能够建立、启动其余线程。java
本质上来说,在Java中建立新线程十分简单,只须要实例化一个Thread
实例便可:segmentfault
Thread t = new Thread();
复制代码
可是当咱们调用该实例的start()
方法来启动线程时,该线程其实什么事情也没干就结束了,缘由是Thread
类中覆写Runnable
接口的run()
方法的方法体以下:多线程
@Override
public void run() {
if (target != null) {
target.run();
}
}
复制代码
这里的target
字段是Runnable
接口的一个实例,而当Thread
构造器没传入任何参数时,target
为null,线程天然也就不会执行任何操做。ide
在Java中,要建立能执行指定代码的新线程,有如下几种方法:学习
Thread
类派生一个自定义类,而后覆写run()
方法。Thread
实例时,传入一个Runnadble
接口的实例,一样要实现接口定义的run()
抽象方法。call()
方法,并包装成FutureTask
类对象,再做为参数传入Thread
的构造器。注意:网站
run()
方法来建立新线程,而run()
方法并没有返回值,因此这两种方法也没法获取返回值。Thread
类,覆写run()
方法public class ExecuteThread {
public static void main(String[] args) {
Thread t = new MyThread();
t.start(); // 启动新线程
}
}
// 继承自Thread的自定义类
class MyThread extends Thread {
@Override
public void run() {
System.out.println("start new thread!");
}
}
复制代码
若是该类型的线程只须要使用一次,也能够用匿名内部类的方式让代码更加简单:编码
public class ExecuteThread {
public static void main(String[] args) {
Thread t = new Thread() {
// 内部匿名类对run()方法的覆写
@Override
public void run() {
System.out.println("start new thread!");
}
};
t.start(); // 启动新线程
}
}
复制代码
Runnadble
接口,实现run()
抽象方法public class ExecuteThread {
public static void main(String[] args) {
Thread t = new Thread(new MyRunnable());
t.start(); // 启动新线程
}
}
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("start new thread!");
}
}
复制代码
或者用Java8引入的Lambda语法进一步简写为:spa
public class ExecuteThread {
public static void main(String[] args) {
Thread t = new Thread(() -> {
System.out.println("start new thread!");
});
t.start(); // 启动新线程
}
}
复制代码
Runnadble
接口,因此能够继承其余的类,避免了单继承的局限性。Runnadble
接口实例,能够被包装成多个线程对象),实现解耦操做,代码和线程独立。call()
方法,并包装成FutureTask
对象传入Thread
构造器public class ExecuteThread {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Callable<String> callableInstance = new MyCallable<>("return value");
// 使用FutureTask类包装Callable接口的实例,该对象封装了Callable接口实现实例的call()方法的返回值。
FutureTask<String> task = new FutureTask<>(callableInstance);
Thread t = new Thread(task);
t.start(); // 启动新线程
// 调用FutureTask实例的get()方法获取新线程执行结束返回值。
System.out.println(task.get());
}
}
class MyCallable<V> implements Callable<V> {
private V toReturn;
public MyCallable (V val) {
toReturn = val;
}
@Override
public V call() throws Exception{
System.out.println("start new thread!");
return toReturn;
}
}
复制代码
Runnadble
实例),能够获取返回值。线程池的使用避免了由于频繁建立、销毁线程带来的大量系统开销,实现了资源的复用。具体的使用方法看这篇笔记:Java多线程学习笔记——如何使用线程池。线程