进程与线程的关系
进程:进程是正在运行的程序的实例(an instance of a computer program that is being executed)。
线程:是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
进程是正在进行的程序,每个正在进行的程序里可能同时干了多件事,每一件事,每一个独立的在执行的流程叫线程。
多线程执行原理 ( 并发执行原理 )
CPU核心: 每一个计算机中CPU核心, 就相当于人的一个大脑, 可以执行一件事情.
时间片: 将CPU未来可以用于执行的时间 ,碎片化, 拆分成一个个的小的时间片段. 每一个时间片段的大小 可以都不足一毫秒.
程序在争抢到时间片段后, 会进行执行 .
Java 实现线程三种方式
方式1. 继承Thread类
1. 编写一个类, 继承Thread类
当调用Thread里的start的方法的时候,本地方法start0会通过C和C++的代码开启新的执行路径(线程),新线程会将Thread的run方法加载进线程执行
2. 重写父类的 run 方法 , 在此方法中调用执行的代码 就是在新的线程中执行的代码.
3. 创建此类的对象, 并调用start方法, 来启动此线程 ;
package com.kkb.demo1;
public class Demo1 {
public static void main(String[] args) {
//当Thread调用start方法时,通过Thread创建一个线程并启动,本地方法start0会通过C、C++代码开启新的执行路径(线程)
//新线程会将Thread里的run方法加载进线程执行,因为源码中的run方法是系统代码,只有自己创建类继承Thread并重写run方法
MyThread1 myThread1 = new MyThread1();
MyThread2 myThread2 = new MyThread2();
myThread1.start();
myThread2.start();
}
}
package com.kkb.demo1;
public class MyThread1 extends Thread {
@Override
public void run() {
for (int i = 1; i < 11; i++) {
System.out.println("甲" + i+1);
}
}
}
package com.kkb.demo1;
public class MyThread2 extends Thread {
@Override
public void run() {
for (int i = 1; i < 11; i++) {
System.out.println("乙" + i);
}
}
}
方式2. 实现Runnable接口
1. 编写一个类, 实现Runnable接口 , 实现run方法 (run方法的逻辑, 就是在新的线程中执行的)
2. 创建上述Runnable接口实现类的 对象
3. 创建Thread对象, 并在构造方法中, 第二步创建的对象
4. 调用Thread对象的start方法,启动线程
多线程的执行,线程的创建格式2,根据源码可知,当调用run方法时,是调用target.run();
Thread里的构造方法 public Thread(Runnable target) 传入的是Runnable类型的target,this.target = target;
如果传入的有target,则调用target的run()
public void run() {
if (target != null) {
target.run();
}
}
package com.kkb.demo1;
public class Demo2 {
public static void main(String[] args) {
MyRunnable1 myRunnable1 = new MyRunnable1();
Thread ts1 = new Thread(myRunnable1);
MyRunnable2 myRunnable2= new MyRunnable2();
Thread ts2 = new Thread(myRunnable2);
ts1.start();//start0>>C代码>>创建线程>>在新线程加载MyRunnable1的run方法
ts2.start();
}
}
package com.kkb.demo1;
public class Demo2 {
public static void main(String[] args) {
MyRunnable1 myRunnable1 = new MyRunnable1();
Thread ts1 = new Thread(myRunnable1);
MyRunnable2 myRunnable2= new MyRunnable2();
Thread ts2 = new Thread(myRunnable2);
ts1.start();//start0>>C代码>>创建线程>>在新线程加载MyRunnable1的run方法
ts2.start();
}
}
package com.kkb.demo1;
public class MyRunnable2 implements Runnable{
@Override
public void run() {
for (int i = 1; i < 11; i++) {
System.out.println("乙" + i);
}
}
}
方式3.匿名内部类
package com.kkb.demo1;
public class Demo3 {
public static void main(String[] args) {
//匿名内部类
new Thread(){
@Override
public void run() {
for (int i = 1; i < 11; i++) {
System.out.println("甲" + i+1);
}
}
}.start();
new Thread(){
@Override
public void run() {
for (int i = 1; i < 11; i++) {
System.out.println("乙" + i);
}
}
}.start();
}
}
面试题:调用start和调用run的区别
start执行逻辑:调用start>>start0>>c代码>>创建线程>>在新线程里调用run
run执行逻辑:调用run直接执行run在当前的线程里执行,只是调用普通方法
面试题:java中存在单线程程序吗?
不存在,Main线程和GC线程,是开始到结束是始终存在的
面试题Java中存在单线程程序吗?
不存在的 . Java在启动时必然存在的有两个线程:
1. main线程
2. GC垃圾回收器