多线程
是提升程序性能非常重要的一种方式,让 CPU 的资源得到充分的利用,提高 CPU 的使用率,从而解决高并发带来的负载均衡问题。
进程和线程
进程:计算机正在运行的一个独立的应用程序,动态
线程是组成进程的基本单位
进程就是正在运行的应用程序,每一个操作都对应一个线程
多线程:在一个进程中,多个线程“同时执行”,合理分配 CPU 资源(单核 CPU 的前提下)
1 个 CPU 不可能同时让两个线程使用,所以某一时刻只能有一个线程使用 CPU,这里的同时执行并不是真正的同时执行,而是交替执行,只是因为运行速度太快,感觉上像是同时执行。
多核 CPU 情况下,才是真正的同时执行
单核 CPU ,需要更合理的分配资源,让 CPU 利用率达到最佳,需要使用多线程
main 方法就是程序入口,是主线程
lambda 表达式,JDK 8 之后引入的新特性,函数式编程:可以将方法的具体实现作为参数进行传递
new Thread(()->{
for (int i = 0; i < 100; i++) {
System.out.println("----------------abc");
}
}).start();
Java 中如何实现多线程
线程和任务
线程是用来执行任务的,任务就是程序要完成的业务需求
如何创建线程,Thread
如何创建任务,Runnable,Callable
public class Runnable1 implements Runnable {
@Override
public void run() {
System.out.println("取快递");
}
}
public class Runnable2 implements Runnable {
@Override
public void run() {
System.out.println("打水");
}
}
public class Test {
public static void main(String[] args) {
Runnable runnable1 = new Runnable1();
Runnable runnable2 = new Runnable2();
Thread thread = new Thread(runnable2);
thread.start();
}
public static void test(int a){
}
}
解耦合 代码更加灵活,更具扩展性
实际开发中,更推荐将线程和任务拆分开进行解耦合的操作,灵活性扩展性更好
1、创建一个实现类来实现 Runnable 接口
public class Runnable1 implements Runnable {
@Override
public void run() {
System.out.println("取快递");
}
}
2、创建 Thread 对象,传入 Runnable
public class Test {
public static void main(String[] args) {
Runnable runnable = new Runnable1();
Thread thread = new Thread(runnable);
thread.start();
}
}
===》优化 匿名内部类
new 一个没有名字同时在 Test 内部定义的一个类
public class Test {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable(){
@Override
public void run() {
System.out.println("做测试");
}
});
thread.start();
}
}
===》优化 使用 lambda 表达式
直接将 run 方法的具体实现作为参数进行传递,抛开外壳只传最核心的即可
public class Test {
public static void main(String[] args) {
Thread thread = new Thread(()->{
System.out.println("做测试");
});
thread.start();
}
}
使用 lambda 表达式的前提
1、参数类型必须是接口
2、接口中只能有一个抽象方法
线程的状态
线程公有 5 种状态,在特定的情况下,线程可以在不同的状态之间切换
- 创建状态:实例化了一个新的线程对象,还未启动
- 就绪状态:创建好的线程对象调用了 start 方法完成启动,进行线程池等待抢占 CPU 资源
- 运行状态:线程对象获取了 CPU 资源,在一定时间内执行任务
- 阻塞状态:正在运行的线程暂停执行任务,释放所占用的 CPU 资源,并在解除阻塞之后不能直接回到运行状态,而是重新回到就绪状态,等待获取 CPU 资源
- 终止状态:线程运行完毕或因为异常导致线程终止运行
一个线程没有开始执行的时候是就绪状态,在执行过程中断了,此时它是阻塞状态,全部执行完毕,此时它是终止状态。
线程调度
1、线程休眠
休眠是指让当前线程暂停执行,从运行状态进入阻塞状态,从而将 CPU 资源让给其他线程的一种调度方式
sleep 方法来实现线程休眠
sleep(long millis) 传入一个 long 类型的数据作为休眠的时间,单位为毫秒,从休眠的那一刻开始计时,到 millis 时间为止,线程都处于休眠状态,时间一过回到就绪状态
public class Test {
public static void main(String[] args) {
Thread thread = new Thread(()->{
for (int i = 0; i < 100; i++) {
if(i == 50){
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i);
}
});
thread.start();
}
}