一.直接使用Thread类创建线程
package lyz.thread;
import lombok.extern.slf4j.Slf4j;
@Slf4j(topic = "c.test1")
public class Test1 {
public static void main(String[] args) {
Thread t = new Thread() {
@Override
public void run() {
log.debug("running");//线程执行的任务
}
};//创建线程
t.setName("t1"); //线程的名字
t.start(); //启动线程
log.debug("running");
}
}
二.实现Runnable接口
package lyz.thread;
import lombok.extern.slf4j.Slf4j;
@Slf4j(topic = "c.test2")
public class Test2 {
public static void main(String[] args) {
Runnable runnable=new Runnable() {
@Override
public void run() {
log.debug("running");
}
};
Thread thread=new Thread(runnable,"t2");
thread.start();
log.debug("running");
}
}
三、Thread 与Runnable 的关系
我们一起看看Runnable接口的代码:
//ps:源码的注释太长了,我删了。。。
package java.lang;
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
我们可以看到这个接口里面只有一个是抽象方法 run(),接口上加了@FunctionalInterface注解,在JDK中会把只有一个抽象方法的接口加上@FunctionalInterface注解,所以我们以后看到接口上面带有@FunctionalInterface,这个接口就可以使用lamba来简化
ps:如果我们看到一个接口中有多个抽象方法,是无法使用lamba来简化的
//lamba表达式
package lyz.thread;
import lombok.extern.slf4j.Slf4j;
@Slf4j(topic = "c.test2")
public class Test2 {
public static void main(String[] args) {
Runnable runnable=()-> {
log.debug("running");
}; //①我们可以手动简化 ②我们可以使用快捷键,把鼠标放在等号后面的 Runnable 上按ALT+Enter(option+Enter)
Thread thread=new Thread(runnable,"t2");
thread.start();
log.debug("running");
}
}
我们来跟一下第二种创建线程的代码,下图所示
进入到Thread对象中:
由代码可知,第二种创建线程的方式还是会用到Thread对象中的run方法,只不过需要判断是否有Runable对象,如果有,就会优先执行Runnable方法中的run()方法。
结论:①不论是第一种还是第二种最终都会执行Thread类中的run()方法
②第一种是把任务跟线程结合在一起了,第二种是把任务与线程分开了
③实现Runnable接口更容易与线程池等高级API结合
④实现Runnable接口使任务类脱离了Thread继承体系,使得代码更加灵活
Ps:在java中,我们是推荐使用组合的方式,组合是优于继承的
四、使用FutuerTask配合Thread类
FutureTask能够接收Callable类型的参数用来处理有返回结果的情况
package lyz.thread;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
@Slf4j(topic = "c.test3")
public class Test3 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建任务对象
FutureTask<Integer> futureTask=new FutureTask<>(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
log.debug("running.....");
return 100;
}
});
//参数1:是任务对象 参数2:是线程名字
Thread thread=new Thread(futureTask,"test3");
//主线程阻塞同步等待futureTask执行完毕之后的结果
log.debug("{}",futureTask.get());
}
}
输出:
[20/04/25 18:46:35 DEBUG] [test3():16] c.test3 - running…
[20/04/25 18:46:35 DEBUG] [main():24] c.test3 - 100
五、多个线程交替并发执行例子
package lyz.thread;
import lombok.extern.slf4j.Slf4j;
@Slf4j(topic = "c.testMultiTread")
public class TestMultiThread {
public static void main(String[] args) {
new Thread(()->{
while (true){
log.debug("running");
}
},"t1").start();
new Thread(()->{
while (true){
log.debug("running");
}
},"t2").start();
}
}