1、进程
- 进程:正在运行的程序
- 是系统进行资源分配和调用的独立单位
- 每一个进程都有它自己的内存空间和系统资源
- 进程的三个特征
- 独立性:进程与进程之间是相互独立的,彼此有自己独立内存区域
- 动态性:进程是运行中的程序,要动态的占用内存,CPU和网络等资源
- 并发性:CPU会分时轮询切换依次为每个进程服务,因为切换的速度非常快,给我们的感觉像是在同时执行,这就是并发性(并发:同一时刻同时有多个在执行)
2、线程
- 线程:进程中的单个顺序控制流,是一条执行路径
- 单线程:一个进程只有一条执行路径
- 多线程:一个进程有多条执行路径
3、多线程的实现方式
3.1、方式一:继承Tread类
-
流程
**1、**定义一个MyTread类继承Tread类
**2、**在MyTread类中重写==run()==方法
**3、**创建MyTread类的对象
**4、**启动线程:对象.start()
-
为什么重写run()方法?
- 因为run()方法是用来封装被线程执行的代码
-
run()和start()方法的区别
- run():封装线程执行的代码,直接调用,相当于普通方法的调用
- start():启动线程,然后由JVM调用此线程中的run()方法
-
示例:
-
MyThread类:
package test; //1、定义一个类MyTread继承Tread类 public class MyThread extends Thread{ //2、在MyTread类中重写run()方法 @Override public void run() { for(int i=0;i<100;i++) { System.out.println(i); } } }
-
测试类:
package test; public class Demo { public static void main(String[] args) { //3、创建MyTread类的对象 MyThread my1 = new MyThread(); MyThread my2 = new MyThread(); //4、启动线程:void start():启动线程,由Java虚拟机调用此线程的run()方法 my1.start(); my2.start(); } }
-
3.2、 方式二:实现Runnable接口
-
流程:
**1、**定义一个MyRunnable类实现Runnable接口
**2、**在MyRunnable类中重写run()方法
**3、**创建MyRunnable类的对象
**4、**创建Tread类的对象,把MyRunnable对啊ing作为构造方法的参数
**5、**启动线程
-
好处:
-
避免了Java单继承的局限性
-
适合多个相同程序的代码去处理同一个资源的情况,把线程和程序的代码、数据有效分离,较好的体现了面向对象的设计理论
-
示例:
package test; public class MyRunnable implements Runnable{ @Override public void run(){ for(int i=0; i<200; i++){ System.out.println("我在看代码--"+i); } } public static void main(String[] args) { //3、创建MyRunnable类的对象 MyRunnable mr = new MyRunnable(); //4、创建Tread类的对象,把MyRunnable对象作为构造方法的参数 //Thread t1 = new Thread(mr); //5、启动线程 //t1.start(); new Tread(mr).start(); for(int i=0; i<200; i++){ System.out.println("我在学习多线程--"+i); } } }
-
3.2、 方式三:实现Callable接口
4、设置和获取线程名称
-
Thread类中设置和获取线程名称的方法
方法名 说明 setName(String name) 将此线程的名称更改为name String getName() 返回此线程的名称 Thread(String name) 通过构造方法也可以设置线程名称 Thread currentThread() 返回对当前正在执行的线程对象的引用(可以返回main()方法中线程) void sleep(long time) 让当前线程休眠多少毫秒再继续执行 -
MyThread类
package test; public class MyThread extends Thread{ //构造方法添加线程名称 public MyThread(){} public MyThread(String name) { super(name); } @Override public void run() { for(int i=0;i<100;i++) { //1,String getName() 返回此线程的名称 System.out.println(getName()+":"+i); } } }
-
测试类
package test; public class Demo { public static void main(String[] args) { /* MyThread my1 = new MyThread(); MyThread my2 = new MyThread(); //2,setName(Stringname) 将此线程的名称更改为等于参数name my1.setName("高铁"); my2.setName("飞机");*/ //3,通过构造方法设置线程名称 //需要自己定义的类中提供此带参构造方法,并通过super访问父类带参构造方法 /*MyThread my1 = new MyThread("高铁"); MyThread my2 = new MyThread("飞机"); my1.start(); my2.start();*/ //4,public static Thread currentThread() 返回对当前正在执行的线程对象的引用(可以返回main()方法中线程) System.out.println(Tread.currentThread().getName()); //main } }
5、线程调度
- 线程有两种调度模型
- 分时调度模型:所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间片
- 抢占式调度模型:优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的CPU时间片相对多一些