什么是进程?
进程是系统进程资源分配和调度的独立单位。每一个进程都有它自己的内存空间和系统资源。
为什么还需要线程呢?
引入线程的主要原因是为了提高系统的执行效率,减少处理机的空转时间和调度切换时间,以及便于系统管理。
- 简单的来说:进程实现多处理非常消耗CPU的资源。
- 在同一个进程内可以执行多个任务,而这每一个任务我们就可以看为一个线程。
进程和线程
定义
- 进程是作为资源分配的基本单位。
- 线程是作为资源调度的基本单位,是程序的的执行单元,是程序使用CPU的基本单位。
线程的3个基本状态
- 就绪
- 执行
- 阻塞
线程的两个基本类型
- 用户级线程:管理过程全部由用户程序完成
- 系统级线程:由操作系统内核进行管理。
并行和并发
并行
- 并行性是指同一时刻内发生两个或多个事件
- 并行是在不同 实体上的多个事件
- 并行是针对进程的
并发
- 并发性是指同一时间间隔内发生两个或多个事件。
- 并发是在同一实体上的多个事件。
- 并发是针对线程的
Java实现多线程
- 继承Thread类,重写run方法
public class MyThread {
public static void main(String[] args) {
Thread thread1 = new Thread(()->{
for (int i = 0; i < 200; i++) {
System.out.println(i);
}
});
Thread thread2 = new Thread(()->{
for (int i = 0; i < 200; i++) {
System.out.println(i);
}
});
thread1.start();
thread2.start();
}
}
- 实现Runnable接口,重写run方法
public class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 200; i++) {
System.out.println(i);
}
}
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable();
Thread thread1 = new Thread(runnable);
Thread thread2 = new Thread(runnable);
thread1.start();
thread2.start();
}
}
- 实现Callable接口,重写call方法
public class MyCallable implements Callable<Integer> {
@Override
public Integer call() {
int num = 0;
for (int i = 0; i < 10; i++) {
num += i;
}
return num;
}
public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
MyCallable myCallable = new MyCallable();
FutureTask<Integer> futureTask = new FutureTask<>(myCallable);
new Thread(futureTask).start();
int i = futureTask.get();
System.out.println(i);
}
}
-
也可以使用搭配
线程池
使用public class MyExecutor { public static void main(String[] args) throws ExecutionException, InterruptedException { ExecutorService executorService = Executors.newCachedThreadPool(); Future<Integer> submit = executorService.submit(() -> { int num = 0; for (int i = 0; i < 10; i++) { num += i; } return num; }); Integer integer = submit.get(); System.out.println(integer); executorService.shutdown(); } }
run方法和start方法的区别
- start()用异步启动线程,启动的线程不会立刻运行,而是就绪状态,在等待队列等待CPU调度,只有线程真正被CPU调度才会调用run()方法。因此,start()方法可以实现多线程。
- 直接调用run()方法就相当于调用一个普通的方法,达不到多线程异步执行。