1 继承Thread 类 重写run方法
启动线程调用start 方法,这样会创建一个新的线程,并且执行线程的任务。
如果直接调用run方法,这样会让当前线程执行run中的业务逻辑
public class MiTest{
public static viod main(String[] arg){
MyJob ti = new MyJob();
ti.start();
for(int i; i<=100; i++){
System.out.println("main" + i);
}
}
}
class MyJob extends Thread(){
@Override
plubic void run(){
for(int i; i<=100; i++){
System.out.println("MyJob" + i);
}
}
}
2 实现Runnable 接口 重写run方法
public class MiTest{
public static viod main(String[] arg){
MyRunnable myRunnable = new MyRunnable();
Thread t1 = new Thread(myRunnable);
t1.start();
for(int i; i<=100; i++){
System.out.println("main" + i);
}
}
}
class MyRunnable implement Thread(){
@Override
plubic void run(){
for(int i; i<=100; i++){
System.out.println("MyRunnable" + i);
}
}
}
这种实现的方式要比继承的好一些,毕竟java 是单继承的;
但是继承Thread 或者 实现Runnable 接口 都是没有返回值得;
3 实现callable 重写call 方法,配合FutureTesk
Callable 一般用于又返回结果的非阻塞执行方法,
同步非阻塞。
public class MiTest{
public static void main (String[] args) throws ExecutionException,InterruptedException{
// 1 创建MyCallable
MyCallable myCallable = new MyCallable();
// 2 创建futureTesk 传入 callable
FutureTesk futureTesk = new FutureTesk(myCallable);
// 3 创建 Thread 线程
Thread thread = new Thread(futureTesk);
// 启动线程
thread.start();
Object count = futureTesk.get();
System.out.println("总和为:"+count);
}
}
class MyCallable implement Callable(){
@Override
public Object call() throws Execption(){
int count = 0;
for(int i = 0; i<=100 ; i++){
count+=i;
}
return count;
}
}
4 基于线程池去构建线程(后续更新)
JDK 中提供了 5 中不同线程池的创建方式,下面我分别说一下每一种线程 池以及它的特点。 1.newCachedThreadPool, 是一种可以缓存的线程池,它可以用来处理大量短期 的突发流量。 它的特点有三个,最大线程数是 Integer.MaxValue,线程存活时间是 60 秒,阻 塞队列用的是 2.SynchronousQueue,这是一种不存才任何元素的阻塞队列,也就 是每提交一个任务给到线程池,都会分配一个工作线程来处理,由于最大线程数 没有限制。 所以它可以处理大量的任务,另外每个工作线程又可以存活 60s,使得这些工作 线程可以缓存起来应对更多任务的处理。 3.newFixedThreadPool,是一种固定线程数量的线程池。 它的特点是核心线程和最大线程数量都是一个固定的值 如果任务比较多工作线程处理不过来,就会加入到阻塞队列里面等待。 4.newSingleThreadExecutor,只有一个工作线程的线程池。 并且线程数量无法动态更改,因此可以保证所有的任务都按照 FIFO 的方式顺序 执行。 newScheduledThreadPool,具有延迟执行功能的线程池 可以用它来实现定时调度 newWorkStealingPool,
Java8 里面新加入的一个线程池 它内部会构建一个 ForkJoinPool,利用工作窃取的算法并行处理请求。
这些线程都是通过工具类 Executors 来构建的,线程池的最终实现类是 ThreadPoolExecutor。
5 .1用lambda 表达式 重写 run方法
Thread t2 = new Thread(()->{
for(i = 0; i<100 i++){
System.out.println("lambda"+i);
}
});
5.2匿名内部类方式
Thread t1 = new Thread(new Runnable(){
@Override
plubic void run(){
for(int i; i<=100; i++){
System.out.println("MyJob" + i);
}
}
})
但是追其底层,只有一种,就是实现 Runnable
1 Thread 类 实现了Runnable,继承 Thread 类 就是间接实现了 Runnable 方法
2 FutureTask 实现了 RunnableFuture接口 ,又继承了Runnable 和 Futrue
3 线程池 每次构建的工作线程都是worker ,worker类 又实现了 Runnable