进程 - 运行中的程序。进程有如下特征:
A. 独立性。拥有自己的资源,拥有自己独立的内存区。
通常来说,一个进程的内存空间,是不允许其他进程访问的。
像Windows,A进程可以通过某种方式修改其他进程的内存值——外挂。
B. 动态性。程序是静止。运行起来才叫进程。
C. 并发性。一个操作系统可以同时“并发(concurrent)”运行多个进程。
线程 - 进程中的“并发(concurrent)”执行流。
Lightweight Process (轻量级进程)
进程与线程的典型区别:Process是有独立内存空间的,因此创建Process的成本
比创建线程的成本要高。
什么“并发”? 什么叫“并行”?
并发:即使只有一个CPU,多个进程,或多个线程在cpu上【快速轮换】的执行。
在一个时刻,只有与CPU个数相同的进程真正在执行。
其他进程都处于等待状态。
——对于用户来说,【感觉】是多个进程在同时执行。
并行(Parallel):必须有一个以上CPU,这样就可以保证在同一个时刻,
至少有与CPU个数相同的进程真正在执行,
这些正在执行的进程就是在并行。
并行:是多个进程【真正在多个cpu】上同时执行。
多线程的好处:
1. 功能上类似多进程。
2. 创建成本又低, 效率高。
3. 所有线程共享进程的内存,因此线程之间通信非常方便。
4. Java语言的多线程非常优秀。
Java的创建多线程的方法(三种):
1. 继承Thread,重写一个run()方法。
—— 这个run()方法就是线程执行体。
什么是线程执行体,就是该线程将要做的事情。
创建Thread的子类的实例即可启动。
2. 实现Runnable,重写一个run()方法。
—— 这个run()方法就是线程执行体。
需要把Runnable对象包装成Thread对象后再启动
3. 实现Callable(就是Runnable增强版),
—— 重写call()方法(有返回值,可以声明抛出异常)。
①. 先把Callable包装成Runnable(FutureTask)
②. 再把Runnable包装成Thread对象后再启动。
而且FutureTask还可以用于获取线程的返回值。
启动线程:
调用Thread对象的start()方法 !!
千万不要调用run方法!!—— 就是普通的方法调用,就不会启动多线程!
创建线程的方式的对比,创建线程的方式可分为2类:
1. 继承Thread类。
2. 实现Runnable或Callable接口。
实现接口的方式更好,原因如下:
A。 实现接口之后,依然可以继承其他类。
但如果继承了Thread类,就无法再去继承别的类。
B。 实现接口时,可以让多个线程共享同一个Runnable对象。
可以更好的实现代码与数据的分离,形成更清晰的逻辑。
实现接口创建多线程唯一的不足是:编程略微复杂一些。
线程的状态
【当调用start之后,只是启动线程,线程并不会立即执行。】
新建 - 刚刚创建出来的Thread对象。
就绪 - 调用start()方法。
运行 -
A. 独立性。拥有自己的资源,拥有自己独立的内存区。
通常来说,一个进程的内存空间,是不允许其他进程访问的。
像Windows,A进程可以通过某种方式修改其他进程的内存值——外挂。
B. 动态性。程序是静止。运行起来才叫进程。
C. 并发性。一个操作系统可以同时“并发(concurrent)”运行多个进程。
线程 - 进程中的“并发(concurrent)”执行流。
Lightweight Process (轻量级进程)
进程与线程的典型区别:Process是有独立内存空间的,因此创建Process的成本
比创建线程的成本要高。
什么“并发”? 什么叫“并行”?
并发:即使只有一个CPU,多个进程,或多个线程在cpu上【快速轮换】的执行。
在一个时刻,只有与CPU个数相同的进程真正在执行。
其他进程都处于等待状态。
——对于用户来说,【感觉】是多个进程在同时执行。
并行(Parallel):必须有一个以上CPU,这样就可以保证在同一个时刻,
至少有与CPU个数相同的进程真正在执行,
这些正在执行的进程就是在并行。
并行:是多个进程【真正在多个cpu】上同时执行。
多线程的好处:
1. 功能上类似多进程。
2. 创建成本又低, 效率高。
3. 所有线程共享进程的内存,因此线程之间通信非常方便。
4. Java语言的多线程非常优秀。
Java的创建多线程的方法(三种):
1. 继承Thread,重写一个run()方法。
—— 这个run()方法就是线程执行体。
什么是线程执行体,就是该线程将要做的事情。
创建Thread的子类的实例即可启动。
2. 实现Runnable,重写一个run()方法。
—— 这个run()方法就是线程执行体。
需要把Runnable对象包装成Thread对象后再启动
3. 实现Callable(就是Runnable增强版),
—— 重写call()方法(有返回值,可以声明抛出异常)。
①. 先把Callable包装成Runnable(FutureTask)
②. 再把Runnable包装成Thread对象后再启动。
而且FutureTask还可以用于获取线程的返回值。
启动线程:
调用Thread对象的start()方法 !!
千万不要调用run方法!!—— 就是普通的方法调用,就不会启动多线程!
创建线程的方式的对比,创建线程的方式可分为2类:
1. 继承Thread类。
2. 实现Runnable或Callable接口。
实现接口的方式更好,原因如下:
A。 实现接口之后,依然可以继承其他类。
但如果继承了Thread类,就无法再去继承别的类。
B。 实现接口时,可以让多个线程共享同一个Runnable对象。
可以更好的实现代码与数据的分离,形成更清晰的逻辑。
实现接口创建多线程唯一的不足是:编程略微复杂一些。
线程的状态
【当调用start之后,只是启动线程,线程并不会立即执行。】
新建 - 刚刚创建出来的Thread对象。
就绪 - 调用start()方法。
运行 -