# 首先看java是怎么执行多线程的
//默认执行Thread对象的run方法。虽然没有显式调用。
@Override
public void run() {
Runnable task = holder.task;
if (task != null) {
Object bindings = scopedValueBindings();
runWith(bindings, task);
}
}
public void start() {
synchronized (this) {
// zero status corresponds to state "NEW".
if (holder.threadStatus != 0)
throw new IllegalThreadStateException();
start0();
}
}
private native void start0();
> 可以看到,真正创建线程的代码是native的。这里其实就是执行当前Thread的run方法里的内容。
>> 当没有重写run时就得有一个Runnable的任务
# java创建线程的方式
1. 继承Thread类,重写run方法。因为线程会默认执行Thread对象的run方法。
public class MyThread extends Thread {
@Override
public void run() {
System.out.println("线程执行:" + Thread.currentThread().getName());
}
}
// 使用
MyThread thread = new MyThread();
thread.start();
2. 使用Runnable作为Thread的构造器参数
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("线程执行:" + Thread.currentThread().getName());
}
}
// 使用
Thread thread = new Thread(new MyRunnable());
thread.start();
或者lamda:
Thread thread = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
System.out.println("Runnable Thread : "+i);
try {
Thread.sleep(1000);
}catch (Exception e){}
}
});
3. 使用FutureTask+Callable 作为Thread的构造器参数,FutureTask其实也是Runnable的子接口
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
return "Hello from " + Thread.currentThread().getName();
}
}
// 使用
Callable<String> task = new MyCallable();
FutureTask<String> futureTask = new FutureTask<>(task);
Thread thread = new Thread(futureTask);
thread.start();
// 获取返回值(阻塞等待)
String result = futureTask.get(); // "Hello from Thread-0"
4. 使用线程池 但是这个的意思其实不是创建新线程了,而是使用将任务提交到线程来执行。ExecutorService的submit会返回Future。
5. CompletableFuture
CompletableFuture<String> future = CompletableFuture.supplyAsync(()->{
System.out.println("in future");
return "future end";
});
System.out.println("in main");
String s = future.get();
System.out.println(s);
//
### FutureTask
public V get() throws InterruptedException, ExecutionException{}
public V get(long timeout, TimeUnit unit){}
阻塞, 可以设置超时时间。其实超过时间了线程还是在运行,只不过读取的这个事件不再阻塞了。