创建和运行线程
方法一,直接使用 Thread
// 创建线程对象
Thread t = new Thread() {
public void run() {// 要执行的任务}
};
// 启动线程
t.start();
例如:
// 构造方法的参数是给线程指定名字,推荐Thread t1 = new Thread("t1") {@Override// run 方法内实现了要执行的任务public void run() {log.debug("hello");}};t1.start();
方法二,使用 Runnable 配合 Thread
把【线程】和【任务】(要执行的代码)分开
- Thread 代表线程
- Runnable 可运行的任务(线程要执行的代码)
Runnable runnable = new Runnable() {public void run() {// 要执行的任务}};// 创建线程对象Thread t = new Thread(runnable);// 启动线程t.start();
例如:
public class Test2 {public static void main(String[] args) {//创建线程任务Runnable r = () -> {//直接写方法体即可System.out.println("Runnable running");System.out.println("Hello Thread");};//将Runnable对象传给ThreadThread t = new Thread(r);//启动线程t.start();}
}
方法三:使用FutureTask与Thread结合
使用FutureTask可以用泛型指定线程的返回值类型(Runnable的run方法没有返回值)
FutureTask 能够接收 Callable 类型的参数,用来处理有返回结果的情况
// 创建任务对象FutureTask<Integer> task3 = new FutureTask<>(() -> {log.debug("hello");return 100;});// 参数1 是任务对象; 参数2 是线程名字,推荐new Thread(task3, "t3").start();// 主线程阻塞,同步等待 task 执行完毕的结果Integer result = task3.get();log.debug("结果是:{}", result);
public class Test3 {public static void main(String[] args) throws ExecutionException, InterruptedException {//需要传入一个Callable对象FutureTask<Integer> task = new FutureTask<Integer>(new Callable<Integer>() {@Overridepublic Integer call() throws Exception {System.out.println("线程执行!");Thread.sleep(1000);return 100;}});Thread r1 = new Thread(task, "t2");r1.start();//获取线程中方法执行后的返回结果System.out.println(task.get());}
}
方式四:使用线程池例如用Executor框架
参数介绍
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {if (corePoolSize < 0 ||maximumPoolSize <= 0 ||maximumPoolSize < corePoolSize ||keepAliveTime < 0)throw new IllegalArgumentException();if (workQueue == null || threadFactory == null || handler == null)throw new NullPointerException();this.acc = System.getSecurityManager() == null ?null :AccessController.getContext();this.corePoolSize = corePoolSize;this.maximumPoolSize = maximumPoolSize;this.workQueue = workQueue;this.keepAliveTime = unit.toNanos(keepAliveTime);this.threadFactory = threadFactory;this.handler = handler;}
* @param corePoolSize the number of threads to keep in the pool, even * if they are idle, unless {@code allowCoreThreadTimeOut} is set
池中一直保持的线程的数量,即使线程空闲也不会释放。除非设置了 allowCoreThreadTimeOut *
@param maximumPoolSize the maximum number of threads to allow in the * pool
池中允许的最大的线程数
* @param keepAliveTime when the number of threads is greater than * the core, this is the maximum time that excess idle threads * will wait for new tasks before terminating.
当线程数大于核心线程数的时候,线程在最大多长时间没有接到新任务就会终止释放, 最终线程池维持在 corePoolSize 大小
* @param unit the time unit for the {@code keepAliveTime} argument
时间单位
* @param workQueue the queue to use for holding tasks before they are* executed. This queue will hold only the {@code Runnable} * tasks submitted by the {@code execute} method.
阻塞队列,用来存储等待执行的任务,如果当前对线程的需求超过了 corePoolSize
大小,就会放在这里等待空闲线程执行。
* @param threadFactory the factory to use when the executor * creates a new thread
创建线程的工厂,比如指定线程名等
* @param handler the handler to use when execution is blocked * because the thread bounds and queue capacities are reached
拒绝策略,如果线程满了,线程池就会使用拒绝策略
运行原理:
1、线程池创建,准备好 core 数量的核心线程,准备接受任务
2、新的任务进来,用 core 准备好的空闲线程执行。
(1) 、core 满了,就将再进来的任务放入阻塞队列中。空闲的 core 就会自己去阻塞队 列获取任务执行
(2) 、阻塞队列满了,就直接开新线程执行,最大只能开到 max 指定的数量
(3) 、max 都执行好了。Max-core 数量空闲的线程会在 keepAliveTime 指定的时间后自 动销毁。最终保持到 core 大小
(4) 、如果线程数开到了 max 的数量,还有新任务进来,就会使用 reject 指定的拒绝策 略进行处理
3、所有的线程创建都是由指定的 factory 创建的。