一:简单回顾
1.java中线程的使用
方式1:继承Thread类
(1)实例
public class MyThread1 extends Thread{
String sign = "This is MyThread1";
@Override
public void run(){
for (int i = 0;i<20;i++){
System.err.println(sign+"->"+i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
方式2:继承Runnable接口
(2)实例
public class MyThread2 implements Runnable {
String myThread2 = "MyThread2";
@Override
public void run() {
for (int i = 0;i < 25;i++){
System.err.println(myThread2+"->"+i);
try {
Thread.sleep(120);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
启动以上线程测试:
(3)实例
public class Main {
public static void main(String[] args) throws InterruptedException {
long startTimeMillis = System.currentTimeMillis();
// 通过实现Runnable接口
MyThread2 myThread2 = new MyThread2();
Thread threadByRunnable = new Thread(myThread2);
// 启动线程
threadByRunnable.start();
// 继承Thread类
MyThread1 myThread1 = new MyThread1();
// 启动线程
myThread1.start();
/* 注意这里不是调运run()方法,而是调运线程类Thread的start方法,在Thread方法内部,会调运本地系统方法,最终会自动调 * 运自己线程类的run方法
*/
// 主线程休眠100ms
Thread.sleep(100);
System.out.println("主线程结束!用时:" + (System.currentTimeMillis() - startTimeMillis));
}
}
运行结果每次都不会相同,这里展示运行结果:
MyThread2->0
This is MyThread1->0
This is MyThread1->1
主线程结束!用时:103
MyThread2->1
This is MyThread1->2
MyThread2->2
This is MyThread1->3
MyThread2->3
This is MyThread1->4
MyThread2->4
This is MyThread1->5
This is MyThread1->6
MyThread2->5
This is MyThread1->7
MyThread2->6
This is MyThread1->8
MyThread2->7
This is MyThread1->9
MyThread2->8
This is MyThread1->10
MyThread2->9
This is MyThread1->11
MyThread2->10
This is MyThread1->12
This is MyThread1->13
MyThread2->11
This is MyThread1->14
MyThread2->12
This is MyThread1->15
MyThread2->13
This is MyThread1->16
MyThread2->14
This is MyThread1->17
MyThread2->15
This is MyThread1->18
This is MyThread1->19
MyThread2->16
MyThread2->17
MyThread2->18
MyThread2->19
MyThread2->20
MyThread2->21
MyThread2->22
MyThread2->23
MyThread2->24
建议:尽量使用Runnable方式实现线程,防止Java单继承的考虑,Runnable面向接口,更容易拓展
二:线程池
(1)为什么使用线程池?
1.降低资源的消耗。主要是降低创建和销毁线程时产生的CPU消耗,线程池通过持续工作的线程执行不断分配的任务,减少线程的创建和销毁。
2.提高响应速度。
3.提高线程的可管理性,线程是稀缺资源,频繁的创建销毁,以及没有控制的大量创建,都会影响系统的稳定性。使用线程池可以统一分配,调优,监控资源。
引用:https://yq.aliyun.com/articles/221709
(2)线程池种类
常见的四种线程池分别为newCachedThreadPool、newFixedThreadPool、newSingleThreadExecutor、newScheduleThreadPool。
四种线程池本质上也是ThreadPoolExecutor,只是这些参数都是固定好了的,我们可以直接使用。
newCachedThreadPool:
/**
* Creates a thread pool that creates new threads as needed, but
* will reuse previously constructed threads when they are
* available, and uses the provided
* ThreadFactory to create new threads when needed.
* @param threadFactory the factory to use when creating new threads
* @return the newly created thread pool
* @throws NullPointerException if threadFactory is null
*/
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),
threadFactory);
}
(1)创建一个可缓存的线程池,如果线程长度超过处理需要,可灵活回收空闲线程,若无可回收线程,创建线程。
(2)工作线程创建数量几乎不受限制(最大数目为Integer.MAX_VALUE),可灵活向线程池中添加线程。
(3)若长时间未向线程池提交任务,如果指定空闲线程时间(默认1分钟),则该工作线程终止。终止后,若新提交任务,线程池重新创建一个工作线程。
(4)在使用newCatchThreadPool,需要控制线程的数量,否则,若大量线程同时运行,造成系统瘫痪。
适合于耗时短,不需要考虑同步的场合。
newFixedThreadPool:
/**
* Creates a thread pool that reuses a fixed number of threads
* operating off a shared unbounded queue, using the provided
* ThreadFactory to create new threads when needed. At any point,
* at most {@code nThreads} threads will be active processing
* tasks. If additional tasks are submitted when all threads are
* active, they will wait in the queue until a thread is
* available. If any thread terminates due to a failure during
* execution prior to shutdown, a new one will take its place if
* needed to execute subsequent tasks. The threads in the pool will
* exist until it is explicitly {@link ExecutorService#shutdown
* shutdown}.
*
* @param nThreads the number of threads in the pool
* @param threadFactory the factory to use when creating new threads
* @return the newly created thread pool
* @throws NullPointerException if threadFactory is null
* @throws IllegalArgumentException if {@code nThreads <= 0}
*/
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory);
}
(1)创建一个指定工作线程数量的线程池,每提交一个任务,创建一个线程,如果工作线程数量达到线程初始化的最大数,将提交的任务存储到线程池指定的工作队列中。
(2)newFixedThreadPool可以提高线程池的效率和节省创建线程时所消耗的开销
(3)在线程空闲时,即线程池中无执行任务时,不会释放工作线程,占用一定的系统资源。
符合常用场合
newSingleThreadExecutor:
/**
* Creates an Executor that uses a single worker thread operating
* off an unbounded queue, and uses the provided ThreadFactory to
* create a new thread when needed. Unlike the otherwise
* equivalent {@code newFixedThreadPool(1, threadFactory)} the
* returned executor is guaranteed not to be reconfigurable to use
* additional threads.
*
* @param threadFactory the factory to use when creating new
* threads
*
* @return the newly created single-threaded Executor
* @throws NullPointerException if threadFactory is null
*/
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory));
}
(1)一个单线程线程池,只有一个线程在工作(若该线程因异常终结,一个新的线程代替),能够保证所有的任务的执行顺序按照提交顺序执行,同一个时段只有一个任务执行。
适用需保证任务执行顺序场景
newScheduleThreadPool:
/**
* Creates a thread pool that can schedule commands to run after a
* given delay, or to execute periodically.
* @param corePoolSize the number of threads to keep in the pool,
* even if they are idle
* @return a newly created scheduled thread pool
* @throws IllegalArgumentException if {@code corePoolSize < 0}
*/
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
(1)创建一个定长的线程池,而且支持定时的以及周期性的任务执行。
(2)可定时运行(初始延时),运行频率(每隔多长时间运行,还是运行成功一次之后再隔多长时间再运行)的线程池
适合定时以及周期性执行任务的场合。