解释:进程的创建也需要申请资源,而申请资源对于系统的性能影响比较大。

举个例子:张三要开一个工厂,工业园相当于是操作系统,地皮是固定的,张三的工厂就像一个进程,生产线就像一个线程,张三的工厂是生产皮包的,里面只有一条生产线,现在我们要提高产量,是重新建一个场比较好?,还是在原来的工厂中加一条生产线好呢?,肯定是只增加一条生产线,这样就节省了工业园地皮的面积资源,也利用张三工厂的面积资源,线程的出现更好的利用了系统的资源。

创建线程比创建进程更快 销毁线程比销毁进程更快 调度线程比调度进程更快。
1.进程里面包含线程:每一个进程里面至少包含一个主线程 2.进程是申请资源的最小单位 3.线程是cpu调度的最小单位 4.进程和进程之间不共享内存空间. 同⼀个进程的线程之间共享同⼀个内存空间 ,所以进程与进程之间互不影响,线程与线程之间可能产生影响 5.一个线程受到影响,会导致进程的结束,⼀个进程挂了⼀般不会影响到其他进程. 但6.是⼀个线程挂了, 可能把同进程内的其他线程⼀起带⾛(整个进程崩溃).

我们先思考下创造进程的方式:

虽然双进程比单进程确实提升了效率,但是消耗资源太大了,太浪费资源了 我们思考创建线程的方法

效率确实提高了,比进程消耗的资源小
我们再思考一下,根据上面的情况,我们无限创建线程,是不是线程创建的越多越好呢?

答案肯定不是的,这样会出现线程争抢资源问题,如果一个线程崩溃就会造成整个进程的崩溃
其实我们可以根据cpu的逻辑处理器来创建线程

当线程小于逻辑处理器,创建线程会提升效率 当线程大于逻辑处理器,创建线程的线程都是阻塞等待状态,从而没有发挥出线程的效果,创建线程本来就会消耗资源,从而白白消耗资源
线程是操作系统中的概念. 操作系统内核实现了线程这样的机制, 并且对⽤⼾层提供了⼀些 API 供⽤⼾使⽤(例如 Linux 的 pthread 库).Java 标准库中 Thread 类可以视为是对操作系统提供的 API 进⾏了进⼀步的抽象和封装.
import java.util.Random; public class ThreadDemo {
private static class MyThread extends Thread {
@Override
public void run() {
Random random = new Random();
while (true) {
// 打印线程名称
System.out.println(Thread.currentThread().getName());
try {
// 随机停⽌运⾏ 0-9 秒
Thread.sleep(random.nextInt(10));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
MyThread t1 = new MyThread();
t1.start();
Random random = new Random();
while (true) {
// 打印线程名称
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(random.nextInt(10));
} catch (InterruptedException e) {
// 随机停⽌运⾏ 0-9 秒
e.printStackTrace();
}
}
} }
我们可以jconsole这个工具查看线程

里面有一个mian主线程,和Thread-0子线程
@Override
//自定义的线程的执行体,线程执行的代码写在这里
public void run(){
while (true){
System.out.println("hello myThread ");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} } class Main{
public static void main(String[] args) {
MyThread myThread=new MyThread();//创建一个线程对象
myThread.start();//启动线程
while (true){
System.out.println("hello mainThread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
1:PCB是操作系统层面的 2:Thread是java层面的线程。两者是一 一对应的 3:过程:java创建一个线程------jvm调用系统API--------创建系统中线程------参与调度cpu

4. 线程执行的顺序是没有规律的,跟cpu的调度有关,因为cpu是“抢占式”执行,所以那个线程当前占用cpu资源是不能确定的 5.能不能调用run()方法执行线程,答案是不行的,因为run方法是java层面的,是不能启动线程的。 6:

start()开始后,并不意味着线程立马执行,

@Override
public void run() {
while (true){
System.out.println("hello myRunnable");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} class Main{
public static void main(String[] args) {
MyRunnable myRunnable=new MyRunnable();//创建一个线程任务对象
// 创建 Thread 类实例, 调⽤ Thread 的构造⽅法时将 Runnable 对象作为 target 参数.
Thread thread=new Thread(myRunnable);//创建一个线程对象,
thread.start();//启动线程
while (true){
System.out.println("hello mainThread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} } ```这种方法实现底层原码过程:

其实这种模式是一种及简化的代理模式,这里模拟实现一下
//模拟实现一个Thread类的代理类,模拟Thread的启动
public class ThreadProxy implements Runnable{
private Runnable target;
public ThreadProxy(Runnable target) {
this.target = target;
}
@Override
public void run(){
if (target!=null){
target.run();
}
}
public void start(){
start0();
}
private void start0() {
run();
}
}
class Main{
public static void main(String[] args) {
// ThreadProxy threadProxy01 = new ThreadProxy(new Runnable() {
// @Override
// public void run() {
// while (true){
// System.out.println("hello myRunnable");
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
// }
// });
// threadProxy01.start();
Tiger tiger = new Tiger();
ThreadProxy threadProxy02 = new ThreadProxy(tiger);
threadProxy02.start();
}
}
class animal {
}
class Tiger extends animal implements Runnable{
public void run(){
System.out.println("老虎嗷嗷叫");
}
}
public class Main {
public static void main(String[] args) {
Thread t1=new Thread(){
@Override
public void run() {
while (true){
System.out.println("hello myThread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t1.start();
}
}public class Main {
public static void main(String[] args) {
Thread t2=new Thread(new Runnable(){
@Override
public void run() {
while (true){
System.out.println("hello myRunnable");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
t2.start();
}
}public class Main {
public static void main(String[] args) {
Thread t3=new Thread(()->{
while (true){
System.out.println("hello myLambda");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t3.start();
}
}
我们这里重提一下,先调用的方法会先入栈,后调用的后入栈,后调用的方法执行完后就会出栈。