01用多线程的目的是什么?
充分利用cpu资源,并发做多件事情。
单核cpu上适不适合用多线程。
适合,如果是单线程,线程中等待io时候,此时cpu就空闲下来了。可以做一件事情,但可以并发做多件事情,分时间片执行,并发和并行不是同一个概念,并行单核满足不了,但它支持并发。
02线程什么时候会让出cpu?
线程结束的时候,写数据的时候,阻塞时候,wait,wait等待io,sleep,和yield。时间片到了,也会让出CPU。
03线程是什么?
是最小的执行单元,一条代码执行流,完成一组代码的执行,这一组代码,我们往往称为一个任务。
04Cpu做的什么工作?
执行代码,任务装入线程,运送执行代码。
05线程是不是越多越好?
线程在Java中是一个对象,每一个Java线程都需要一个操作系统线程来支持。线程创建、销毁需要时间。如果创建时间+销毁时间>执行时间就很不合算。
Java对象占用堆内存,操作系统线程占用系统内存,根据jvm规范,一个线程默认最大栈大小1M,这个栈空间是需要从系统内存中分配的。线程过多,会消耗很多内存。
操作系统需要频繁操作线程上下文,影响性能。
06该如何正确使用多线程?
多线程目的:充分利用cpu并发做事,线程的本质是代码送给cpu执行,这合适的线程数量就构成了一个池,有任务要执行,就放入池中,池中的一个线程将把任务运送到cpu中执行。
public class ExecutorsDemo {
private static ExecutorService executor = Executors.newFixedThreadPool(15);
public static void main(String[] args) {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
executor.execute(new SubThread());
}
}
}
class SubThread implements Runnable {
@Override
public void run() {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
//do nothing
}
}
}
我们把jvm参数调的消协,比如-Xmx8m -Xms8m 。运行下刚才写的代码,会抛出异常内存溢出。
我们在创建线程池的初始化容量就可以了,比如
private static ExecutorService executor = new ThreadPoolExecutor(10, 10,
60L, TimeUnit.SECONDS,
new ArrayBlockingQueue(10));
Guava也提供了一个良好的线程池创建方式
public class ExecutorsDemo {
private static ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
.setNameFormat("demo-pool-%d").build();
private static ExecutorService pool = new ThreadPoolExecutor(5, 200,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
public static void main(String[] args) {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
pool.execute(new SubThread());
}
}
}
07上万并发的程序设计中,开多少线程合适?
如果是计算型任务,cpu数量的1-2倍,如果是io任务,则需要多一些线程,要根据具体的io阻塞时长进行考量决定,如tomcat默认的最大线程为200。
也可考虑根据需要在一个最小数量和最大数量间自动增减线程数。