问题1、用多线程的目的是什么?
充分利用CPU资源,并发做多件事。
问题2、单核CPU机器上适不适合用多线程?
适合,如果是单线程,线程中需要等待IO时,此时CPU就空闲出来了。
问题3、线程什么时候会让出CPU?
1)、阻塞时(wait,await,等待IO)
2)、sleep
3)、yield(让出CPU,但也会立刻参与竞争CPU资源)
4)、线程执行结束
问题4、线程是什么?
一条代码执行流,完成一组代码的执行;
这一组代码,我们往往称为一个任务。
问题5、CPU做的是什么工作?
运算,执行代码
问题6、线程是不是越多越好?
创建线程需要花费时间,一次性使用,用完了要销毁,销毁也需要时间。
1)、线程在JAVA中是一个对象,每一个JAVA线程都需要一个操作系统纯种支持。线程创建、销毁需要时间。如果创建时间+销毁时间>执行任务时间就很不划算。
2)、JAVA对象占用堆内存,操作系统线程占用系统内存,根据JVM规范,一个线程默认最大栈1M,这个栈空间是需要从系统内存中分配的。线程过多,会消耗很多的内存。
3)、操作系统需要频繁切换线程上下文(大家都想被运行),影响性能。
问题7、该如何正确使用多线程?
1)、多线程的目的:充分利用CPU并发做事(多做事)
2)、线程的本质:将代码送给CPU执行
3)、用合适数量的线程不断运送代码即可,这合适数量的线程就构成了一个线程池
4)、有任务要执行,就放入线程池,池中的一个线程将把任务运送到CPU中执行。
线程池原理揭秘
1)、任务用什么表示?
Runnable
Callable(对Runnable的改进,可以返回值,也可以抛出异常)
2)、仓库用什么?
BlockingQueue阻塞队列,线程安全的。
问题8、如何确定合适数量的线程?
1)、如果是计算型任务:CPU数量的1-2倍
2)、如果是IO型任务:要根据具体的IO阻塞时长进行合理决定(比如tomcat默认最大线程数是200),也可以根据需要在一个最小数量和最大数量间自动增减线程数
JAVA线程池API
JAVA并发包中提供了丰富的线程池实现。
接口类Executor:只有一个接口方法 void execute(Runnable command);
接口类ExecutorService:加入了Callable、Future、关闭方法等
接口类ScheduledExecutorService
实现类ThreadPoolExecutor:线程池的标准实现
Callable:对Runnable的改进,可以返回值,可以抛出异常。
Future:异步任务监视器,让提交者可以监控任务的执行。
Executors:创建线程池的工厂类,减轻我们的任务,它的工厂方法:
newFixedThreadPool(int nThreads) 创建一个固定大小、任务队列容量无界的线程池。池的核心线程数=最大线程数=nThreads
newScheduledThreadPool(int corePoolSize) 能定时执行任务的线程池。该池的核心线程数由参数指定,最大线程数=Integer.MAX_VALUE