提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
并发
程序:是程序员书写的功能代码。
线程:线程是一个执行单元或执行场景。
进程:处于运行中的程序。
一个进程中包含至少一个线程。
多线程
多个线程协同工作,共同完成一件事情,目的提升了执行效率。
代码从main开始执行,main()方法调用了,谁调用了main,当然是JVM,JVM启动了一个线程,开始调用main方法,这个线程叫main线程(主线程),JVM还会启动一个线程,是垃圾回收线程,负责回收不用的对象。所以java命令执行,后台至少启动了两个线程。
线程开发方式
继承Thread类
class A extends Thread {}
此处的Thread
类,是线程的超级根类。 线程所在包:java.lang包。
其次,线程运行结果是不固定的。因为CPU 负责线程的调度, 调用为随机的,有个执行的时间。规定A线程执行2秒 cpu中有一个时间片,可以规定线程执行多长时间,故线程之间是争抢cpu资源的。
多线程时,各线程有专属名字。线程之间句有优先级,级别为1-10极,默认为5级。
使用Runnable接口
class A implements Runnable {
public void run(){
}
}
//实现方式
使用实现接口 Runnable
的对象创建一个线程时,启动该线程将导致在独立执行的线程中调用对象的 run()
方法。
用匿名类开发线程
new 要继承的父类 / 要实现的接口() {
父类中要实现的方法 / 接口中要实现的方法() {
……
}
}
线程状态
基础状态
- 初始状态(新建状态):
new
的过程。 - 就绪状态(可运行状态):调用
start()
,调用时会自动运行内部的run()
方法。 - 运行状态 :被cpu选中(资源调用)。
- 结束(终止)状态
阻塞状态
sleep()
sleep()
:让该线程进入休眠状态。目的:多个线程同时运行时,让低优先级线程可以得到运行的机会。
sleep(long millis)
:让线程在启动后的millis时间后进入休眠状态。
join()
join()
:等待该线程终止。在多个线程运行中,如果一个线程让另外一个线程join()
进来,那么当前的这个线程会让加入的线程先执行完毕,然后自己再接着执行。当两边线程相互join()
时,则会出现死锁现象。无法根除,但可以通过设置等待时间使阻塞影响减少到最小。
join(long millis)
:等待该线程终止的时间最长为 millis 毫秒。millis为 0 意味着要一直等下去。
yield()
yield()
:暂停当前正在执行的线程对象,并执行其他线程。当运行中的多个线程具有相同优先级时,让其他线程得到运行机会。但是下一次运行的可能是其他线程,也可能还是自己。
停止与中断
停止
线程停止使用布尔变量来进行。
class A extends Thread{
private boolean flag; //布尔变量控制线程
//返回开关状态
public boolean isFlag(){
return flag;
}
//传入flag状态
public void setFlag(boolean flag) {
this.flag = flag;
}
@Override
public void run(){
for (int i = 0; i < 10; i++) {
//开关;
if (flag){
break;
}
……
}
}
}
外部调用内部方法使线程停止
public static void main(String[] args) {
A a = new A1();
a.start();
//进程
try {
……
}catch (InterruptedException e){
e.printStackTrace();
}
a.setFlag(true); //停止
}
中断
中断线程使用interrupt()
方法。gai方法并不会中断一个正在运行的线程。但是,如果线程被阻塞(sleep、join、wait),就会抛出一个中断信号,这样线程就得以退出阻塞的状态,使阻塞状态的线程逃离阻塞状态,并继续运行。
public class Test {
public static void main(String[] args) {
Runnable r = new P1();
Thread t1 = new Thread(r, "线程1");
t1.start();
t1.interrupt(); //调用中断方法
}
}
class P1 implements Runnable{
@Override
public void run(){
……
try {
Thread.sleep(millis); //millis为自己定的毫秒时间
}catch (InterruptedException e){
…… //被interrupt方法调用后的操作
}
……
}
}