目录
1.继承Thread类,重写它的run方法;
package classFile;
class MyThread extends Thread{
@Override
public void run() {
System.out.println("子线程");
}
}
public class ThreadTest {
public static void main(String[] args) {
Thread thread = new MyThread();
thread.start();
}
}
2.实现Runnable接口,实现其run方法;
package classFile;
class MyThread implements Runnable{
@Override
public void run() {
System.out.println("子线程");
}
}
public class ThreadTest {
public static void main(String[] args) {
Runnable task = new MyThread();
Thread thread1 = new Thread(task);
thread1.start();
}
}
说明:本质上Thread类也是实现了Runnable接口
3.通过创建FutureTask的对象来实现(带返回值);
package classFile;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class ThreadTest {
public static void main(String[] args) throws Exception {
Callable<Integer> callable = new Callable() {
@Override
public Integer call() throws Exception {
System.out.println("子线程要执行的方法");
return 12;
}
};
FutureTask task = new FutureTask(callable);
// FutureTask间接实现了Runnable接口
Thread thread = new Thread(task);
thread.start();
// 要获取子线程的返回值
Integer o = (Integer) task.get(); //主线程等待子线程返回结果
System.out.println(o);
}
}
结果:
4.通过匿名内部类的方式;
package classFile;
public class ThreadTest {
public static void main(String[] args) throws Exception {
Thread thread = new Thread(){
@Override
public void run() {
System.out.println("子线程");
}
};
thread.start();
}
}
当然由于Thread类实现了函数式接口Runnable,所以可以使用lambda表达式来简化操作:
package classFile;
public class ThreadTest {
public static void main(String[] args) throws Exception {
Thread thread = new Thread(()-> System.out.println("子线程"));
thread.start();
}
}
注意:lambda表达式是java8的新特性,知识体系比较丰富,建议读者单独花时间学习。
5.线程池的方式;
说明:创建线程的方式那么多了,为什么还需要线程池呢?原因之一是:在高并发场景下,不使用线程池情况下,应用程序在每个用户访问时可能都会创建单独的线程,用户访问完毕后,则销毁线程,而创建和销毁线程的开销又是巨大的,且耗内存空间,所能够支持的并发量并不多。而通过线程池,则可以实现线程的复用,节省了大量开销。
代码如下:(使用了ForkJoinPool)
package 并发3;
import javax.persistence.criteria.CriteriaBuilder;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
public class 基于分治思想的线程池的使用 {
public static void main(String[] args) {
ForkJoinPool forkJoinPool = new ForkJoinPool(2); //线程池线程的数量
long start = System.currentTimeMillis();
forkJoinPool.invoke(new MyTask(1000)); //线程池执行任务
System.out.println("任务耗时-没优化的并发"+(System.currentTimeMillis()-start));
// 单线程
long start2 = System.currentTimeMillis();
doSum(1000);
System.out.println("任务耗时--串行"+((System.currentTimeMillis())-start2));
// 任务拆分下的多线程
ForkJoinPool forkJoinPool1 = new ForkJoinPool(2);
long start3 = System.currentTimeMillis();
forkJoinPool1.invoke(new MyTask1(1,1000));
System.out.println("优化的并发"+(System.currentTimeMillis()-start3));
}
// 单线程递归 1+...+n的和
public static Integer doSum(int n){
if (n == 1){
return 1;
}
return doSum(n-1) + n;
}
}
// 1-5整数和
// 这种拆分方法并发度不高
class MyTask extends RecursiveTask<Integer>{
private int n;
@Override
protected Integer compute() {
if (n == 1){
return 1;
}
MyTask t1 = new MyTask(n-1);
t1.fork(); //让一个线程执行任务
int result = n + t1.join();
return result;
}
public MyTask(int n){
this.n = n;
}
}
输出结果:
注释:不同的pc运行结果可能不同,读者可自己测试。