简介
线程创建方式由继承Thread类,实现Runnable接口,实现Callable接口通过FutureTask包装,通过线程池来创建,所以本文主要介绍Java线程方式。
继承Thread类
Thread本质是实现Runnable接口的一个实例。实现如下:
/**
- 继承Thread类创建线程
*/
public class MyThread extends Thread {
/**
* 重写run()方法来实现自己的业务需求
*/
@Override
public void run() {
//打印线程名称及id
System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().getId());
System.out.println("启动线程Thread");
}
}
public static void main(String[] args) {
//main 方法是一个线程
System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().getId());
System.out.println("============调用其他线程start============");
//Thread方法创建线程
MyThread myThread = new MyThread();
myThread.start();
//Runnable方法创建线程
// MyRunnable myRunnable = new MyRunnable();
// new Thread(myRunnable).start();
System.out.println("============调用其他线程end==============");
}
实现Runnable接口
当一个类中已经继承了其他类,还要实现线程,就只能采用实现Runnable接口
/**
* 实现Runnable接口创建线程
*/
public class MyRunnable implements Runnable {
/**
* 重写run()方法来实现自己的业务需求
*/
@Override
public void run() {
//打印线程名称及id
System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().getId());
System.out.println("启动线程Runnable");
}
}
public static void main(String[] args) {
//main 方法是一个线程
System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().getId());
System.out.println("============调用其他线程start============");
//Thread方法创建线程
// MyThread myThread = new MyThread();
// myThread.start();
//Runnable方法创建线程
MyRunnable myRunnable = new MyRunnable();
new Thread(myRunnable).start();
System.out.println("============调用其他线程end==============");
}
Callable
/**
* 实现Callable接口创建线程
* @param <String>
*/
public class MyCallable<String> implements Callable<String> {
/**
* 重写run()方法来实现自己的业务需求
* @return
*/
@Override
public String call() {
System.out.println("启动线程callable");
return (String)"启动线程callable";
}
}
public static void main(String[] args) {
//main 方法是一个线程
System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().getId());
System.out.println("============调用其他线程start============");
//Thread方法创建线程
// MyThread myThread = new MyThread();
// myThread.start();
//Runnable方法创建线程
// MyRunnable myRunnable = new MyRunnable();
// new Thread(myRunnable).start();
//Callable方法创建线程
MyCallable<String> myCallable = new MyCallable<>();
//由Callable<String>创建一个FutureTask<String>对象:
FutureTask futureTask = new FutureTask(myCallable);
//注释:FutureTask<String>是一个包装器,它通过接受Callable<String>来创建,它同时实现了Future和Runnable接口。
//由FutureTask<String>创建一个String对象:
Thread thread = new Thread(futureTask);
thread.start();
System.out.println("============调用其他线程end==============");
}
通过线程池方式来创建线程
- 通过Executors来创建线程池
import java.util.concurrent.*;
public class MyExecutors {
/**
* 非自定义注解
* @param args
*/
public static void main(String[] args) {
//1.newSingleThreadExecutor():创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定的顺序来执行;
//(FIFO,LIFO,优先级)
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 5; i++) {
System.out.println("=================newSingleThreadExecutor()=================");
//存在返回值;可进行Exception处理
Future result = singleThreadExecutor.submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
//判断该任务是否在完成前取消
System.out.println("result:" + result.isCancelled());
singleThreadExecutor.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
System.out.println("=================newSingleThreadExecutor()=================");
}
// 关闭线程池
singleThreadExecutor.shutdown();
//2.newFixedThreadPool(int nThreads):创建定长线程池,控制线程的最大并发数量,超出的线程会在队列中等待;
//nThreads:线程最大并发数量
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
System.out.println("=================newFixedThreadPool(5)=================");
fixedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
System.out.println("=================newFixedThreadPool(5)=================");
}
fixedThreadPool.shutdown();
//3.newCachedThreadPool():创建一个可缓存线程池,若线程长度超过处理需求,可灵活回收空闲的线程,没有空闲线程,则新建线程
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
System.out.println("=================newCachedThreadPool()=================");
cachedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
System.out.println("=================newCachedThreadPool()=================");
}
cachedThreadPool.shutdown();
//4.newScheduledThreadPool():创建拥有固定线程数量,支持定时线程及周期请任务的线程池
//schedule参数:3(delay)-从现在开始延迟执行的时间 TimeUnit.SECONDS-延迟参数的时间单位
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);
System.out.println("newScheduledThreadPool开始时间:" + System.currentTimeMillis());
for (int i = 0; i < 5; i++) {
scheduledExecutorService.schedule(new Runnable() {
@Override
public void run() {
System.out.println("newScheduledThreadPool执行时间:" + System.currentTimeMillis() + "--" + Thread.currentThread().getName());
}
}, 3, TimeUnit.SECONDS);
}
System.out.println("newScheduledThreadPool结束时间:" + System.currentTimeMillis());
scheduledExecutorService.shutdown();
//5.newSingleThreadScheduledExecutor():线程池中存在多个线程时,各个线程不同调度来执行,互不影响;当一个线程遇到阻塞时,其他线程都会收到影响被阻塞,但依旧会按照自身的调度来执行,但是会受到阻塞延迟
ScheduledExecutorService singleThreadScheduledExecutor = Executors.newSingleThreadScheduledExecutor();
System.out.println("newSingleThreadScheduledExecutor开始时间:" + System.currentTimeMillis());
for (int i = 0; i < 5; i++) {
singleThreadScheduledExecutor.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
System.out.println("newSingleThreadScheduledExecutor执行时间:" + System.currentTimeMillis() + "--" + Thread.currentThread().getName());
}
}, 0,3, TimeUnit.SECONDS);
}
System.out.println("newSingleThreadScheduledExecutor结束时间:" + System.currentTimeMillis());
}
singleThreadScheduledExecutor.shutdown();
}
- 通过ThreadPoolExecutor 来自定义创建线程池
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class MyThreadPoolExecutor {
public static void main(String[] args) {
//自定义线程池 参数讲解
/*
int corePoolSize:核心线程数(不会被回收)
int maximumPoolSize:最大线程数
long keepAliveTime:当线程数大于核心时,这是多余空闲线程在终止前等待新任务的最长时间
TimeUnit : 参数时间单位
BlockingQueue<Runnable> : 线程的阻塞队列(必须有界)
ThreadFactory : 产生线程的工厂
RejectedExecutionHandler : 当线程大于总数(最大线程数 + 阻塞队列)时,将由handler拒绝任务
*/
ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 20, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(100), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
MyThread myThread = new MyThread();
for (int i = 0; i < 10; i++) {
executor.execute(myThread);
}
//关闭线程池
executor.shutdown();
}
注:线程池得创建一般不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,可避免资源耗尽的风险。
1) newFixedThreadPool和newSingleThreadExecutor: 堆积的请求处理队列可能会耗费非常大的内存
2)newCachedThreadPool和newScheduledThreadPool: 线程数最大数是Integer.MAX_VALUE,可能会创建数量非常多的线程
结尾
本文到这里就结束了,感谢看到最后的朋友,都看到最后了,点个赞再走啊,如有不对之处还请多多指正。
网友评论