多线程
进程和线程:
进程:正在执行的程序。
线程:一条独立的执行路径。
一个进程可以只有一条线程,也可以有多条线程。
多线程
Java中至少有两个线程:主线程和垃圾回收线程。
多线程:具有完成特定功能的执行路径,是CPU最先执行单位。
CPU在某个时间刻度上只能够执行一条线程的一条原子性语句。
只不过CPU切换执行速度非常快,我们无法察觉以为是同时执行。
多道编程的意义:
提高CPU的利用率。一个线程在执行任务的过程中,有一部分时间在CPU
上进行计算, 另一部分时间和硬件进行IO交互。线程在进行IO操作的时
候是不会利用CPU的。
1 0.8 0.2
2 0.8*0.8=0.64 0.36
3 0.8*0.8*0.8=0.512 0.488
多线程的执行流程图如下:
多线程的启动方式
方式一:继承Thread类
public class MyThread extends Thread { @Override public void run() { System.out.println(Thread.currentThread().getName() + "--线程开始执行---"); } public static void main(String[] args) { Thread thread = new Thread(new MyThread()); thread.start(); } }
方式二:实现Runnable接口
可以避免由于Java单继承带来的局限性
public class MyRunnable { public static void main(String[] args) { // 匿名内部类 Thread thread = new Thread(new Runnable() { @Override public void run() { System.out.println("Runnable 创建线程"); } }); thread.start(); } }
方式三:实现Callable方式开启线程
实现Runnable和实现Callable接口的区别
1.有返回值
2.可以声明异常
这里的返回值和异常抛出都是给到线程的启动者
import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class MyCallable implements Callable<Integer> { @Override public Integer call() throws Exception { int sum = 0; for (int i = 0; i < 5; i++) { System.out.println(i); sum += i; } return sum; } public static void main(String[] args) { FutureTask<Integer> task = new FutureTask<>(new MyCallable()); Thread t = new Thread(task); t.start(); for (int i = 0; i < 5; i++) { System.out.println("main" + i); } try { Integer value = task.get(); System.out.println(value); } catch (InterruptedException | ExecutionException e) { System.out.println("子线程抛出异常给主线程" + e); e.printStackTrace(); } System.out.println("over"); } }