1.并发与并行
1.1并发
- 并发:指两个或多个时间在同一时间段内发生(交替执行)
1.2并行
- 并行:指两个或多个时间在同一时刻发生(同时发生)
2.线程和进程
2.1进程
是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程
进程也是程序一次执行过程,是系统运行程序的基本单位,系统运行一个程序即是一个进程从创建,运行
到消亡的过程
2.2线程
线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程,也可以有多个线
程,这个应用程序也可以称之为多线程程序
如下图的例子!!!
3.线程的调度
3.1分时调度
所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU时间
3.2抢占式调度
抢先让优先级高的线程使用CPU,如果线程的优先级相同,会随机选择一个(线程随机性),Java使用的便是
抢占式
4.创建多线程的方式
4.1继承Thread类
- 1.继承Thread类,并重写run()方法,该方法代表了线程需要完成的任务,称之为线程执行体
- 2.创建Thread子类的实例,即创建了线程对象
- 3.开启线程调用start()启动线程
public class PrimeThread extends Thread{
long minPrime;
PrimeThread(long minPrime){
this.minPrime = minPrime;
}
public void run(){
// 执行自己的业务...
}
}
public static void main(String[] args){
// 实例化子类
PrimeThread p = new PrimeThread(122);
// 启动线程
p.start();
}
4.2实现Runnable接口重写run方法
- 1.实现Runnable接口,并重写run方法
- 2.创建Thread线程类,将实现Runnable接口的类的实例,放入到Thread的构造器中,并调用start方法
public class PrimeThread implements Runnable{
long minPrime;
PrimeThread(long minPrime){
this.minPrime = minPrime;
}
@Override
public void run(){
// 执行自己的业务...
}
}
public static void main(String[] args){
// 实例化子类
PrimeThread p = new PrimeThread(122);
// 启动线程
new Thread(p).start();
}
5.多线程例子
5.1例子
!!!上代码!!!
public class MyThread implements Runnable{
@Override
public void run(){
for(int i=0;i<20;i++){
System.out.println("run:"+i);
}
}
}
public static void main(String[] args){
// 实例化子类
MyThread mt = new MyThread();
// 启动线程
mt.start();
for(int i=0;i<20;i++){
System.out.println("main:"+i);
}
}
!!!结果!!!
5.2执行过程
- 1.JVM执行main方法,创建一个main方法的线程
- 2.当代码执行到new MyThread();的时候,会创建一个新的线程
- 3.两个线程同时抢夺CPU的时间片来执行线程,谁抢到了谁就执行代码
!!!由此可见多线程的结构!!!
- 当调用run方法时,属于单线程,并且被当作普通方法调用,在main线程里执行
- 当调用start方法时,会开辟一个新的栈空间并执行底层run方法,属于多线程
- CPU会根据哪个线程抢得时间片而优先执行哪个线程
- 多线程之间,线程与线程互不影响
6.Thread类
下图为常用的Thread方法
7.Runnable接口
- 1.定义Runnable接口的实现类,重写该接口的run方法,该run方法的方法体同样是该线程知兴替
- 2.创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象
- 3.调用线程对象的start方法启动线程
public class MyRunnable implements Runnable{
@Override
public void run(){
for (int i=0;i<20;i++){
System.out.println(Thread.currentThread().getName()+""+i);
}
}
}
public class Demo{
public static void main(String[] args){
MyRunnable mr = new MyRnnable();
//实例化Thread 并调用start方法启动线程
new Thread(mr).start();
for (int i=0;i<20;i++){
System.out.println(Thread.currentThread().getName()+""+i);
}
}
}
!!!打印台显示结果!!!
8.Thread和Runnable的区别
- 如果一个类继承Thread,则不适合资源共享,如果实现了Runnable接口,则很容易实现资源共享
- 可以避免java中单继承的局限性
- 增加程序健壮性,实现解耦操作,代码可以被多个线程共享,代码和线程独立
- 线程池只能放入实现Runnable和Callable类线程,不能放入继承Thread的类