1、继承Thread类
使用便利,但Java是单继承,继承了Thread类就不能继承其它类了
public class ThreadTest extends Thread{
public void run() {
System.out.println(currentThread().getName());
}
public static void main(String[] args) {
ThreadTest thread1 = new ThreadTest();
ThreadTest thread2 = new ThreadTest();
thread1.start();
thread2.start();
}
}
2、实现Runnable接口
使用接口,避免了单继承的局限
public class ThreadTest implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args) {
ThreadTest threadTest = new ThreadTest();
Thread thread1 = new Thread(threadTest, "线程1");
Thread thread2 = new Thread(threadTest, "线程2");
thread1.start();
thread2.start();
}
}
3、使用FutureTask方法
以上两种创建方法都不带返回值,而用FutureTask方法创建线程,则有返回值
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class ThreadTest implements Callable<String> {
@Override
public String call() {
String name = Thread.currentThread().getName();
return name;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<String> futureTask = new FutureTask<>(new ThreadTest());
Thread thread1 = new Thread(futureTask, "线程1");
Thread thread2 = new Thread(futureTask, "线程2");
thread1.start();
thread2.start();
System.out.println(futureTask.get());
}
}
同样,我们创建了两个线程,都开始运行,但是最终结果却只有一个返回值,为什么?
那是因为我们使用FutureTask的时候,只能有一个返回值,如果多个线程同时使用,则后执行的线程的返回值,会覆盖之前的返回值,所以最终只会有一个返回值
4、线程池创建线程
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static java.lang.Thread.sleep;
public class ThreadTest{
public static void main(String[] args) {
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0 ; i < 3 ; i++) {
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
cachedThreadPool.execute(() -> System.out.println(Thread.currentThread().getName()));
}
}
}
由结果我们可以看到,每次执行都是在同一个线程池中使用同一个线程,因为这种方法可以不创建新的线程,而是一个线程执行完当前任务后,就可以去执行下一个任务,不必新建
(不建议使用Executors去创建,因为会由于任务过多而导致内存溢出)
建议使用ThreadPooLExecutor的方式去创建线程池
创建守护进程
public class ThreadTest {
public static void main(String[] args) {
Thread daemonThread = new Thread(() -> {
System.out.println("创建一个守护进程");
});
// 设置为守护进程
daemonThread.setDaemon(true);
daemonThread.start();
}
}
- 如果创建一个用户线程,那么即使主线程已经执行完,JVM还要等所有用户线程也执行完,才可以退出。
- 如果创建一个守护线程,那么主线程执行完之后,JVM不用等守护线程退出,而是直接退出。
ps -eaf|grep java // 查看JVM进程
你的坏机器人 发布了16 篇原创文章 · 获赞 16 · 访问量 4921 私信 关注如果你希望在主线程结束后JVM进程马上结束,那么在创建线程时可以将其设置为守护线程,如果你希望在主线程结束后子线程继续工作,等子线程结束后再让JVM进程结束,那么就将子线程设置为用户线程