java 多线程学习 线程基础 && 创建线程的5种方法
多线程基本概念
进程和线程分别是什么线程
进程是资源分配的基本单位
线程是执行的基本单位,多个进程之前可以共享进程的资源
cpu
cpu只做计算
如果发生线程切换 则需要操作系统进行调度。
线程的切换
- 单核cpu设置多线程是否有意义
有意义
因为不是所有任务都消耗cpu,比如等待网络响应。
这时候可以把cpu让出来让另一条线程继续进行cpu运算。
- 线程数是不是越多越好
不是,因为线程切换存在消耗,如我开10000 个线程 程序就会在线程里来回切换,反而降低了效率。
线程池 设置多少个线程比较合适
这取决于 线程里的操作,多久在计算,多久在进行网络io等待。
需要注意一点,如果这台机器上不止一个应用,那么要考虑其他机器也需要用到线程,操作系统也需要用到线程,所以得均衡考虑。
以下是公式
具体 需要wait 多久 这完全取决于你各个行为的并发数等,这个初期无法预估,得通过统计,可以通过profiler推算。
线程的5种创建方式
- 继承thread
- 实现Runnable接口
继承thread和实现Runnable接口哪个更好?
实现Runnable接口更好,因为实现runnable 接口,还可以实现别的接口,而继承不行所以runnable 更灵活
- 使用lambda (和new Thread()其实是一样的)
- 线程池,其实就是管理Thread 的池子,防止线程数过多。
- 实现Callable 和Runnable 的区别是,Callable 是一个带返回值的模型。Callable 会返回Future对象,Future.get 可以堵塞等待线程执行完毕。
ExecutorService executor = Executors.newCachedThreadPool();
// 线程池接收一个Callable,将返回值存储到Future对象中
var future = executor.submit(() -> {
System.out.println("callable done");
return 1;
});
Thread.sleep(10000);
// 如果线程执行完毕,则直接返回,如果未执行完毕则阻塞到线程返回。
System.out.println(submit.get());
由于new Thread() 不能直接传callable 所以得通过一层转换,代码如下。
new Thread( new FutureTask(() -> {
System.out.println("callable done");
return 1;
}));