一:为什么要使用线程:
如果是单核单线程的情况下,其实使用多线程操作,不一定有使用单线程快,只不过,随着硬件的发展,计算机的核心数和线程数主逐渐增长,所以使用多线程,可以提供更好的效率
二:Java线程的创建
Java创建线程的方式有两种,第一种是继承Tread的类,第二种是实现Runnable接口并将它作为构造参数传入Thread的对象里面。这两种方法都需要调用Thread的run()方法来开启线程。
三:Java线程池的创建
对于系统来说,我们单独创建线程是不明智的,因为,jvm每创建一个线程,就会给对应的线程分配资源,如果无限制的创建线程,最终可能会导致资源使用完,从而系统崩溃。针对需要创建线程的时候,我们可以创建一个线程池来执行相关操作
在java中,为我们提供了现有的创建线程池的方法:
//创建一个线程池,池里面只有一个线程corePoolSize和maxumuPoolSize的值都是1
Executors.newSingleThreadExecutor();
//创建一个可以动态扩容的线程池corePoolSize是0和maxumuPoolSize的值是int的最大值
Executors.newCachedThreadPool();
//创建一个固定大小的线程池corePoolSize是4和maxumuPoolSize的值是int的最大值4
Executors.newFixedThreadPool(4);
上面这三种方式,其实内部都是调用了ThreadPoolExecutor的构造方法,只不过是传递的corePoolSize和maxumuPoolSize的值不同,构造方法如下:
public ThreadPoolExecutor(
int corePoolSize,//核心数
int maximumPoolSize //线程池最大的线程数,
long keepAliveTime, //当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间
TimeUnit unit,//keepAliveTime时间单位
BlockingQueue<Runnable> workQueue,//当线程池中的线程都在工作是,用于存放后来新增的任务的线程队列
ThreadFactory threadFactory,//创建线程的工厂类,继承ThreadFactory可以设置线程的名字
RejectedExecutionHandler handler//当workQueue队列已经满的时候,使用的拒绝策略
) {
四:线程池的 submit(Callable<T> task) 和 execute(Runnable command) 的区别:
这个两个方法本质上没有却别,最终调用的execute(Runnable command) 方法,只不过,submit(Callable<T> task) 在调用execute之前封装了一个Future,所以,使用submit()方法,可以调用Future的get方法,来获取线程执行的结果.就是因为这一层的封装,所以真正执行的Runnable对象是不同的,summit使用的是RunnableFuture对象,execute使用的是自己new的Runnable对象.
这个可以自己实现一个线程池,覆盖 beforeExecute(Thread t, Runnable r){}方法验证.