一、本章主旨
常见的线程实现方法有如下四种:
- 1.继承Thread并重写run方法;
- 2.实现Runnable接口并重写run方法,将其实例作为形参传入Thread构造;
- 3.通过Callable和Future Task创建线程;
- 4.线程池创建管理线程;
- 3方式相较于1、2来说,有两个不同:一是
Callable
的call()
方法有返回值,可以获取任务执行结果;二是Callable
可以抛异常,而Runnable
只能通过setDefaultUncaughtExceptionHandler()
方式才能在主线程中捕获子线程异常; - 阿里开发手册中有讲到,不允许显示的创建线程,而是通过线程池的方式,来更大效率利用资源,避免系统内存等异常;同时也不允许使用
Executors
工具类创建线程池,因为无法对线程池资源做明确定义和限制,同样存在OOM资源耗尽风险,所以采用自定义的ThreadPoolExecutor
更为合适;
1
FixedThreadPool
和SingleThread Pool
允许的请求队列长度为Integer.MAX_VALUE
,可 能会堆积大量的请求,从而导致 OOM。
2CachedThreadPool
和ScheduledThreadPool
允许的创建线程数量为Integer.MAX_VALUE
可能会创建大量的线程,从而导致 OOM。
二、线程的状态
图片源自《码出高效:Java开发手册》
三、使用
3.1 Thread
//1.继承Thread并重写run()
public class MyThread extends Thread{
@Override
public void run() {
//重写run()
for (int i = 0; i < 100; i++) {
System.out.println(i);
}
}
}
//2.调用
public class ThreadDemo {
public static void main(String[] args) {
MyThread m1 = new MyThread();
m1.start();
}
}
3.2 Runnable
//1.实现Runnable接口重写run方法
public class MyRunnableThread implements Runnable {
public void run() {
//重写run()
for (int i = 0; i < 100; i++) {
System.out.println(i);
}
}
}
//2.Runnable实现类的实例对象作为Tread构造函数的target调用
public class ThreadDemo {
public static void main(String[] args) {
MyRunnableThread m1 = new MyRunnableThread();
Thread t1 = new Thread(m1);
t1.start();
}
}
3.3 Callable 和 FutureTask
Callable
里的call()
类似于Runnable
中的run()
,但是其无法作为构造参数传入Thread
,因为构造中只支持Runnable
;
所以,才有了Future Task
包装类,对其进行二次封装,优化返回获取等方法,再传入Thread
;
public class FutureTask<V> implements RunnableFuture<V>{}
//1.实现Callable接口
public class MyCallThread implements Callable {
public Object call() throws Exception {
for (int i = 0; i < 3; i++) {
Thread.sleep(1000);
System.out.println("线程循环次数:" + i);
}
return "执行成功";
}
}
//2.调用并获取执行状态
public class MultiThread {
public static void main(String[] args) {
Callable callable = new MyCallThread();
//返回值类型为String
FutureTask futureTask = new FutureTask<String>(callable);
Thread thread = new Thread(futureTask);
try {
//主线程休息
Thread.sleep(5000);
thread.start();
System.out.println("futureTask.get():" + futureTask.get());
System.out.println("over");
} catch (Exception e) {
e.printStackTrace();
}
}
}
线程循环次数:0
线程循环次数:1
线程循环次数:2
futureTask.get():执行成功
over
3.4 ThreadPoolExecutor
自定义线程池,包含线程工厂、拒绝策略、线程池创建;
/**
* 创建线程工厂
*/
public class UserThreadFactory implements ThreadFactory {
private final String namePrefix;
private final AtomicInteger nextId = new AtomicInteger(1);
//使创建的线程名称有意义,方便溯源
UserThreadFactory(String whatFeatureOfGroup) {
namePrefix = "UserThreadFactory's " + whatFeatureOfGroup + "-Worker-";
}
public Thread newThread(Runnable task) {
String name = namePrefix + nextId.getAndIncrement();
Thread thread = new Thread(null, task, name, 0);
System.out.println("thread -" + name + "-created");
return thread;
}
}
/**
* 拒绝策略
*/
public class UserRejectHandler implements RejectedExecutionHandler {
public void rejectedExecution(Runnable task, ThreadPoolExecutor executor) {
System.out.println("task reject :" + executor.toString());
}
}
/**
* 线程池
*/
public class MyThreadPool {
public static void main(String[] args) {
//1.缓存队列长度设置
BlockingQueue blockingQueue = new LinkedBlockingQueue(2);
//2.创建两个线程工厂
UserThreadFactory factory1 = new UserThreadFactory("华南1机房");
UserThreadFactory factory2 = new UserThreadFactory("华南2机房");
//3.超限拒绝策略handler
UserRejectHandler rejectHandler = new UserRejectHandler();
//4.创建线程池并设定参数
ThreadPoolExecutor threadPoolFirst = new ThreadPoolExecutor(
2, 2, 60,
TimeUnit.SECONDS, blockingQueue, factory1, rejectHandler);
ThreadPoolExecutor threadPoolsecond = new ThreadPoolExecutor(
1, 2, 60,
TimeUnit.SECONDS, blockingQueue, factory2, rejectHandler);
Runnable task = new Task() {
@Override
protected Object call() throws Exception {
return "执行成功";
}
};
for (int i = 0; i < 10; i++) {
threadPoolFirst.execute(task);
}
}
}