每日一狗(田园犬西瓜瓜)

该类实现了Runnable接口,
简化写法
Thread t = new Thread(()->{
System.out.println("左手");
});
| 方法名 | 干啥的 | 备注 |
|---|---|---|
| void start() | 告诉线程,你可以开始执行了,执不执行不确定 | 到达可运行状态(就绪) |
| void run() | 这个线程是干啥的 | |
| void setName(String) | 修改线程名 | |
| setPriority(int); | 更改线程优先级(java中1-10,越大越高) | java有10级,但是不同的操作系统不一定支持10种,要用就不要太像,距离拉大,防止56映射到同一优先级中(建议使用1、5、10) |
| void setDaemon(boolean) | 设置守护线程,在start之前设置 | 用于为其他提供服务的线程,(打辅助的,AD寄了,奶妈活着也没必要了,进程中的其他线程都是AD),一般情况下这都会用死循环,因为守护线程会自动终止 |
| void interrupt() | 中断线程,不是中断线程的执行,而是修改中断参数 | 具体实现是抛了一个异常,然后就啥也没有了,线程还是在运行,终止要你自己实现 |
| boolean isAlive() | 测试线程是否处于活动状态,活动状态就是线程已经启动且尚未终止。线程处于正在运行或准备开始运行的状态,就认为线程是“存活”的 | |
| void join()/(long millis) | 等待改线程终止 | 无参没有时间,就硬等,带参最长时间未millis毫秒,参数为0时代表无限制等待 |
| static void yield() | 将线程从 运行 转到 就绪状态 | |
| static void sleep(long millisec) | 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响 | |
| static Thread currentThread() | 返回对当前正在执行的线程对象的引用 |
Runnable接口只定义了一个方法public void run(),这个方法要求实现Runnable接口的类实现,Runnable对象称为可运行对象,一个线程的运行就是执行该对象的run()方法。
在运行线程的时候不能直接调用run方法,需要用Thread.start()来通知线程,你可以开始执行了,去执行吧!直接调用run方法就想到于是先当前线程执行该方方法一样,和普通方法无异。
问题:继承Thread或实现Runnable接口这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果。 如果需要获取执行结果,就必须通过共享变量或者使用线程通信的方式来达到效果,这样使用起来就比较麻烦。
解决问题:call()方法有返回值,这个返回值可以通过泛型进行约束,还允许抛出异常
Future表示一个任务的生命周期,并提供了方法来判断是否已经完成或取消以及获取任务的结果和取消任务等。
Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果。
cancel 用来关闭一个任务
isCancelled 方法表示任务是否被取消成功
isDone 方法表示任务是否已经完成,若任务完成,则返回true
有用的方法
FutureTask实现了RunnableFuture,RunnableFuture又继承了Runnable, Future接口,FutureTask就实现了Runnable和 Future,所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。
FutureTask在构造的时候传入Runnable、Callable最后都会变成Callable。
public FutureTask(Runnable runnable, V result) {
this.callable = Executors.callable(runnable, result);
this.state = NEW; // ensure visibility of callable
}
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
}
具体使用
FutureTask<Integer> future = new FutureTask<Integer>(callable);
new Thread(future).start();
FutureTask是一个可取消的异步计算,FutureTask实现了Future的基本方法,提供start cancel 操作,可以查询计算是否已经完成,并且可以获取计算的结果。结果只可以在计算
完成之后获取,get方法会阻塞当计算没有完成的时候,一旦计算已经完成, 那么计算就
不能再次启动或是取消。
一个FutureTask 可以用来包装一个 Callable 或是一个Runnable对象。因为FurtureTask实现了Runnable方法,所以一个 FutureTask可以提交(submit)给一个Excutor执(excution). 它同时实现了Callable, 所以也可以作为Future得到Callable的返回值。
ThreadPoolExecutor是线程池框架的一个核心类,线程池通过线程复用机制,并对线程进行统一管理 。
特性
// runState 存储在高阶位中
private static final int RUNNING = -1 << COUNT_BITS;
private static final int SHUTDOWN = 0 << COUNT_BITS;
private static final int STOP = 1 << COUNT_BITS;
private static final int TIDYING = 2 << COUNT_BITS;
private static final int TERMINATED = 3 << COUNT_BITS;
线程池中的核心线程数。当提交一个任务时,线程池创建一个新线程执行任务,直到当前线程数等于corePoolSize;如果当前线程数为corePoolSize,继续提交的任务被保存到阻塞队列中,等待被执行。
线程池中允许的最大线程数。如果当前阻塞队列满了,且继续提交任务,则创建新的线程执行任务,前提是当前线程数小于maximumPoolSize。
线程空闲时的存活时间。默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,如果一个线程空闲的时间达到keepAliveTime,则会终止,直到线程池中的线程数不超过corePoolSize。但是如果调用allowCoreThreadTimeOut(boolean)方法,keepAliveTime参数也会起作用,直到线程池中的线程数为0。
keepAliveTime参数的时间单位。
例如TimeUnit.DAYS
任务缓存队列,用来存放等待执行的任务。如果当前线程数为corePoolSize,继续提交的
任务就会被保存到任务缓存队列中,等待被执行。
一般来说,这里的BlockingQueue有以下三种选择:
线程工厂,创建新线程时使用的线程工厂。
任务拒绝策略,当阻塞队列满了,且线程池中的线程数达到maximumPoolSize,如果继续提交任务,
就会采取任务拒绝策略处理该任务,线程池提供了4种任务拒绝策略:
特性:newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收重用时则新建线程。
应用:用来创建一个可以无限扩大的线程池,适用于服务器负载较轻,执行很多短期异步任务。
new ThreadPoolExecutor(0,
Integer.MAX_VALUE,
60L,
TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
创建一个固定大小的定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
应用:因为采用无界的阻塞队列,所以实际线程数量永远不会变化,适用于可以预测线程数量的业务中,或者服务器负载较重,对当前线程数量进行限制
特性:newScheduledThreadPool创建一个定长线程池,支持定时及周期性任务执行可以延时启动,定时启动的线程池。
应用:适用于需要多个后台线程执行周期任务的场景
特性:newSingleThreadExecutor创建一个单线程化的线程池它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO先进先出, LIFO后进先出, 优先级)执行
应用:适用于需要保证顺序执行各个任务,并且在任意时间点,不会有多个线程是活动的场景
特性:
newWorkStealingPool:创建一个拥有多个任务队列的线程池,可以减少连接数创建当前可用cpu数量的线程来并行执行,适用于大耗时的操作,可以并行来执行
ExecutorService提供提交任务的方式
线程池框架提供了两种方式提交任务,submit()和execute(),
通过submit()方法提交的任务可以返回任务执行的结果,
通过execute()方法提交的任务不能获取任务执行的结果。 void execute(Runnable command);
ExecutorService的方法:关闭线程池
shutdownNow:对正在执行的任务全部发出interrupt(),停止执行,对还未开始执行的任务全部取消,并且返回还没开始的任务列表
shutdown:当调用shutdown后,线程池将不再接受新的任务,但也不会去强制终止已经提交或者正在执行中的任务
3<<3; // 3*2^3=24