作者
:学Java的冬瓜
博客主页
:☀冬瓜的主页
专栏
:【JavaEE】
分享
:愉快骑行的一天!
主要内容
:为什么使用并发编程?进程和线程之间的关系、创建线程的5种方式、怎么在电脑上查看线程和进程运行的情况。
目的就是为了利用现在多核CPU的资源,让程序跑的快
。目前CPU已经有5nm芯片,再往小了做难度很大,因为经典力学失效,开始涉及量子力学。
1> 进程是操作系统进行资源分配的基本单位
。对于进程来说,大量的时间花在了申请资源/释放资源上;线程则省掉了申请资源/释放资源时间,把时间集中用于调度上,因为所有线程共享它们所处进程中的资源,不需要自己再去申请和释放资源。所以线程速度更快。
2> 线程是操作系统进行调度执行的基本单位
。进程主要负责资源分配,线程主要负责调度执行。
3> 线程比进程创建、销毁、调度的速度要快
。线程是轻量级的进程。
并不是线程越多,程序越快。当线程足够多时,大量的时间就用于线程之间的调度切换,反而速度减慢,而且如果线程过多,还可能导致资源耗尽(内存,宽带等),导致其它线程无法使用。
多进程比多线程更稳定
。因为在多线程中,如果有一个线程异常,可能整个进程就崩了,该进程中的其它线程也会挂掉。而多进程中则进程之间相互独立,互不干扰。因此浏览器一般使用多进程编程模型,从而防止一个页面出现异常时,其它开好的页面全部崩掉。
多进程更安全,但是多线程更快,因此使用多线程然后解决多线程的问题是我们需要去训练的
。同一个进程中的线程共享进程中的资源,所以很容易引发线程安全问题。而进程安全问题,在进程间通信时,可能会发生。
内存和文件描述符表
)一组PCB描述一个进程,每一个PCB描述一个线程
。所以一个进程可能有一个线程,也可能有多个线程。进程中的这一组的内存指针和文件描述符表共用一份,状态、上下文、优先级、记账信息则每个pcb各有自己的一份。class MyThread extends Thread{
@Override
public void run() {
System.out.println("继承Thread类,重写run()!");
}
}
public class ThreadTest {
public static void main(String[] args) {
// 法一:继承Thread,重写run()
Thread t1 = new MyThread();
t1.start(); // 创建一个线程
}
}
class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("实现Runnable接口,重写run()!");
}
}
public class ThreadTest {
public static void main(String[] args) {
// 法二:runnable类实现Runnable接口,重写run(),再实例化线程对象
// 1.描述一个任务
Runnable runnable = new MyRunnable();
// 2.将任务交给线程来执行
Thread t2 = new Thread(runnable);
t2.start();
}
}
public class ThreadTest {
public static void main(String[] args) {
// 法三:继承Thread类,重写run(),使用匿名内部类
Thread t3 = new Thread(){
@Override
public void run() {
System.out.println("继承Thread类,重写run(),使用匿名内部类!");
}
};
}
}
public class ThreadTest {
public static void main(String[] args) {
// 法四:实现Runnable接口,重写run(),使用匿名内部类!
Thread t4 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("实现Runnable接口,重写run(),使用匿名内部类!");
}
});
}
}
public class ThreadTest {
public static void main(String[] args) {
// 法五:使用lambda表达式
Thread t5 = new Thread(()->{
System.out.println("使用lambda表达式!");
});
}
}
public class ThreadTest {
public static void main(String[] args) {
t1.start(); // start()是创建一个线程
t2.start();
t3.start();
t4.start();
t5.start();
System.out.println("Hello main Thread!");
}
}
运行结果:由于操作系统调度线程是抢占式执行,执行顺序是不确定的!!!
继承Thread类,重写run()!
Hello main Thread!
实现Runnable接口,重写run()!
实现Runnable接口,重写run(),使用匿名内部类!
使用lambda表达式!
继承Thread类,重写run(),使用匿名内部类!
C:\Program Files\Java\jdk版本\bin\jconsole.exe
),这里就可以连接进程,并查看这个进程中的信息。// 法三:继承Thread类,重写run(),使用匿名内部类
Thread t3 = new Thread(){
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("继承Thread类,重写run(),使用匿名内部类!");
}
}
};