一、进程:
正在运行的程序。是程序的一次执行过程,或是正在运行的程序
二、线程
进程的一个实体,一个进程可以拥有多个线程
单线程:同一个时刻,只允许执行一个线程
多线程:同一个时刻,允许执行多个线程
并发:同一时刻,多个任务交替执行,单核CPU实现的多任务就是并发
并行:同一时刻,多个任务同时执行,多核CPU可以实现并行
三、线程的创建和运行
1.继承Thread类
自定义一个类classXX继承Thread类,重写Thread的run()方法(准确的说是实现Runnable接口的抽象方法run(),因为Thread实现了Runnable接口),在run方法中写自己的业务代码。开启线程需要new一个classXX然后调用该类的start方法。
当运行程序main主函数时会开一个进程,这个进程会开一个主线程,程序就会在该线程下执行。
但如果在主线程下开一个子线程,主子线程是异步的,不管主从其中一个线程结束后进程不会结束,只有所以线程都结束了进程才会结束。
为何要使用start方法而不直接调用run方法开启线程?
答:因为run方法本身就是一个普通方法,直接调用run方法不会真正的开启一个新的线程,会等到run方法执行结束后才会向下执行。此时调用该方法的线程是main线程,不会是Thread-X线程。
start方法的底层?
start方法内部调用了start0(),是个native修饰的本地方法由JVM调用,可以理解为JVM通过该方法的底层逻辑启动多线程调用run方法
2.实现Runnable接口
由于Java是单继承的,当一个类已经继承了他的父类就无法通过继承Thread类来操作了,所以此时可以实现Runnable接口。
自定义类classXX,实现Runnable接口,重写run方法
然后在别类中new个Thread,Thread thread = new Thread(classXX),由于Runnable接口没有start方法,所以需要通过静态代理的方法让Thread类帮我们调用start方法创建新线程执行run方法。
/* Thread类的静态代理 通过Thread thread = new Thread(classXX)将classXX赋值给target, thread.start()->start0()JVM内部创建新线程调用Thread类的run,该run里最终调用回classXX的run方法 */ private Runnable target; public Thread(Runnable target) { this(null, target, "Thread-" + nextThreadNum(), 0); } @Override public void run() { if (target != null) { target.run(); } }
四、线程的终止
自己给循环条件loop设置一个能够外部修改loop的setLoop方法,满足终止条件后调用setLoop方法将线程里的loop修改为false中止。
五、线程常用方法
六、线程的生命周期
其中Runnable状态可细分为 Ready 和 Running状态
当new了一个线程对象该线程就处于NEW状态
调用sleep休眠方法会使线程进入Timed_Waiting状态
七、线程的同步和异步
//在静态方法中实现同步代码块
public static void m1(){
synchronized(类名.class){ //因为静态方法是属于类本身的,所以上的锁对象是该类
}
}
//非静态方法
public void m2(){
synchronized(this){//上锁的对象是调用该方法的实例对象,所以用this
}
}