目录
引入进程的目的
引入进程这个概念,是为了解决“并发编程”这样的问题。CPU 进入了多核心的时代,要想进一步提高程序的执行速度,就需要充分的利用 CPU 的多核资源。
弊端
进程太重了(速度慢、消耗资源多)
1.创建一个进程,开销比较大。
2.销毁一个进程,开销也比较大。
3.调度一个进程,开销也比较大。
进程重,主要是重在资源分配和回收。
线程
线程也叫做“轻量级进程”。
目的就是解决并发编程问题的前提下,让创建、销毁、调度的速度,更快一点。
轻的原因:省下了**“申请资源和释放资源”**的操作。
进程和线程的区别(面试题)
- 进程包含线程,每个进程至少有一个线程存在,即主线程。
- 进程和进程之间不共享内存空间。一个进程的线程之间共享同一个内存空间。
- 进程是系统分配资源的最小单位,线程是系统调度的最小单位。
多线程的优势-增加运行速度
假设张三租了个房子和一台机器,生产零件,零件的销量不错,于是他决定提高生产效率,那么怎样可以提高生产效率呢?
方法一:
再租一个房子、买一台机器,生产零件
方法二:
在房子1中买入一台机器2,和机器1一起生产零件
很明显,第二种方法更节约成本,此时它们共享一套资源。
第一个多线程程序
多线程程序和普通程序的区别:
- 每个线程都是一个独立的执行流
- 多个线程之间是“并发”执行的
Java中进行多线程编程该如何实现呢?
在Java标准库中,就提供了一个Thread类,来表示/操作线程。
Thread类的基本用法
写法一:使用继承Thread,重写run的方式来创建线程
通过Thread类创建线程有很多种方法,最简单的就是创建子类继承Thread,重写run()方法。
Thread t = new MyThread();//创建 MyThread 类的实例
t.start();//启动线程
class MyThread extends Thread{
@Override
public void run() {
System.out.println("hello Thread");
}
}
public class ThreadDemo1 {
public static void main(String[] args) {
Thread t = new MyThread();
t.start();
}
}
run()方法体中描述了这个线程内部要执行的代码。
需要调用这里的start方法,才是真正在系统中创建了线程,才开始真正执行上面的run操作。
运行结果如下:
再写一个程序来观察线程的执行情况,通过 while 循环来打印语句、sleep方法控制打印的速度。
class MyThread extends Thread{
@Override
public void run() {
while(true) {
System.out.println("hello Thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class ThreadDemo1 {
public static void main(String[] args) {
Thread t = new MyThread();
t.start();
while(true){
System.out.println("hello main");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
运行结果如下:
根据代码我们可以发现两个线程,都是打印一次,休眠1s(1000ms)。那么,当1s时间到了,谁会先被唤醒呢?
通过运行结果可以看到,唤醒的顺序是随机的。这种随机性,会给多线程编程造成很多麻烦!!
写法二:使用Runnable interface来描述线程入口
创建一个类,实现 Runnable 接口,再创建Runnable实例(new MyRunnable )传给Thread。
代码如下:
class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("hello Thread");
}
}
public class ThreadDemo2 {
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable();
Thread t = new Thread(runnable);
t.start();
System.out.println("hello main");
}
}
运行结果如下:
- while 循环,观察执行情况
代码如下:
class MyRunnable implements Runnable{
@Override
public void run() {
while (true){
System.out.println("hello Thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class ThreadDemo2 {
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable();
Thread t = new Thread(runnable);
t.start();
while(true){
System.out.println("hello main");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
运行结果如下:
写法三:继承Thread,使用匿名内部类
1.创建一个匿名内部类,继承Thread类;
2.重写run方法;
3.new 这个匿名内部类的实例
代码如下:
public class ThreadDemo3 {
public static void main(String[] args) {
Thread t = new Thread(){//匿名内部类
@Override
public void run() {
System.out.println("hello Thread");
}
};
t.start();
System.out.println("hello main");
}
}
运行结果如下:
- while 循环,观察执行情况
代码如下:
public class ThreadDemo3 {
public static void main(String[] args) {
Thread t = new Thread(){//匿名内部类
@Override
public void run() {
while(true){
System.out.println("hello Thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t.start();
while(true){
System.out.println("hello main");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
运行结果如下:
写法四:实现Runnable,使用匿名内部类
使用匿名类创建 Runnable 子类对象
代码如下:
public class ThreadDemo4 {
public static void main(String[] args) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
while(true){
System.out.println("hello Thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
t.start();
while(true){
System.out.println("hello world");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
运行结果如下:
写法五:lambda表达式的基本写法(需掌握)
lambda 表达式创建 Runnable 子类对象
代码如下:
public class ThreadDemo5 {
public static void main(String[] args) {
Thread t = new Thread( ()->{
while(true){
System.out.println("hello Thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
);
t.start();
while(true){
System.out.println("hello main");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
运行结果如下:
希望大家可以学会以上五种写法,多写几次,lambda表达式的基本写法一定要掌握!!