无论是自己定义的线程还是jvm内部创建的线程,核心在于制定一个任务给线程,让线程知道接下来要做什么任务。
制定任务的方式一般是:重写run/使用runnable/使用lambda...
这是上一节内容(线程的创建方法)
关于线程属性的设置都要放在start之前设置,一旦线程已经启动,就没法再设置线程属性。(开弓没有回头箭)
**1、**isDaemon():是否为后台线程
区分前后台线程
前台线程:前台线程不结束,Java进程一定不结束;一个进程中的所有前台线程结束,进程才会结束。
后台线程(守护线程):后台线程继续执行,也不能阻止进程结束。
java
/**
* 关于线程属性的设置都要放在start之前设置,一旦线程已经启动,就没法再设置线程属性。(开弓没有回头箭)
*
* // 线程属性
* 1、getId():获取id,此处的线程id是jvm自己弄得一套id体系和系统中pcb上的id是不同的。Java代码也无法获取到pcb中的id。
* 2、getName():名称
* 3、getState():状态
* 4、getPriority():优先级
* 5、isDaemon():是否为后台线程
* 前台线程:前台线程不结束,那么Java进程一定不会结束。一个进程中所有前台线程结束,进程才会结束。
* 后台线程(daemon):后台线程(守护线程)继续执行,也不能阻止Java进程结束。(在jconsole中看到的jvm中包含一些其他的内置线程,就属于后台线程)
* gc(垃圾回收):是周期性持续性执行的线程,不可能主动结束,所以一般设置为后台线程。
* gc线程和main线程同属于同一个进程中。进程结束,则所有线程结束。
* 6、isAlive():是否存活
* 此处的属性:指的是系统中的线程(PCB)是否还存在。
* Thread对象的生命周期 和 PCB的生命周期 是不一定一样的。
* 7、isInterrupted():是否被终止
* 终止线程,在Java中都只是提醒建议,真正要不要终止需要线程本身来决定是否要终止。
*/
public class thread_attribute {
public static void main(String[] args) {
// 使用lambda创建一个线程
Thread thread = new Thread(()->{
for (int i = 0; i < 3; i++) {
System.out.println("前台线程:线程结束,进程结束");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
thread.start();
// 此时thread默认是前台线程,thread执行完才结束进程。
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("设置为后台线程:无论线程是否结束,都无法阻止进程结束。进程结束,线程就强行结束。");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
// 此处将线程设置为后台线程
thread1.setDaemon(true);
thread1.start();
}
}
2、isInterrupted():是否被终止
终止线程:在Java中都只是提醒建议,是否要终止线程由当前程序员编写代码是否终止。
以下代码是自己写的一个控制终止线程,写这个段代码是遇到了一些问题!
自定义变量终止线程代码
java
/**
* 线程的核心操作
* 1、start:执行start方法,才是真正将线程创建出来,并执行线程。
* 每个线程都是独立调度执行的,相当于整个程序中多了一个执行流。
* 一个Thread对象只能start一次。
* 2、isInterrupted():是否被终止
* 终止线程,在Java中都只是提醒建议,真正要不要终止需要线程本身来决定是否要终止。
*/
public class thread_method {
private static boolean isRunning = true;
/**
* // 在声明isRunning这个变量是犯了一个错误,我将这个变量声明到了main方法中。
*
* main方法是一个静态方法,其作用范围仅限于方法内部,变量的作用范围仅限于局部变量,因此变量不能有访问控制修饰符。
*
* private:主要用于修饰类成员(字段/方法),因而private修饰符适用于类级别的字段和方法,而不适用于方法内部的局部变量。
* static:
* 类级别变量:变量用static修饰,并且声明在类体内但方法外部,则变量属于类级别变量。所有实例共享同一个变量。
* 局部变量:变量没有static修饰,则为局部变量,仅在方法的作用范围内有效。
*/
public static void main(String[] args) {
// boolean isRunning = true;
/**
* // boolean isRunning = true;
* isRunning: 声明为局部变量,在此代码中是编译不了的。(这错误卡在了javac编译阶段,和jvm运行时没有关系)
*
* 变量捕获:作为lambda或者匿名内部类,都能捕获到外面一层作用域中的变量名,就可以使用的。
* 变量捕获:有一个前置条件,就是变量得是final或者"事实"final,这样才能被捕获的,否则就不能被捕获。
*
* isRunning此处不能报错,不能捕获的原因是:isRunning在下面被更改为了false,并不能"事实"final,所以不能被捕获。
* 解决方法:将下面isRunning的修改删除,此段代码就不会报错了。但是就达不到控制终止程序的效果。
*/
// 自己写一个控制终止线程
Thread thread = new Thread(() -> {
// 终止线程结束的方式有:控制循环条件、是否return...
while(isRunning) {
/**
* 此处的isRunning是 内部类 访问 外部类的成员变量。
*/
System.out.println("线程任务");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println("线程已终止");
});
thread.start(); // 创建线程并执行线程
try {
Thread.sleep(5000); // 5秒后结束线程,那么就需要改变控制条件
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("终止线程");
isRunning = false;
}
}
private、static修饰作为修饰符(上段代码 中的问题一**)**
private:
主要用于修饰类成员(字段/方法),因而private修饰符适用于类级别的字段和方法,而不适用于方法内部的局部变量。
static:
类级别变量:变量用static修饰,并且声明在类体内但方法外部,则变量属于类级别变量。所有实例共享同一个变量。
局部变量:变量没有static修饰,则为局部变量,仅在方法的作用范围内有效。
main方法是一个静态方法,其作用范围仅限于方法内部,变量的作用范围仅限于局部变量,因此变量不能有访问控制修饰符。
变量捕获(上段代码 中的问题二**)**
isRunning: 声明为局部变量,在此代码中是编译不了的。(这错误卡在了javac编译阶段,和jvm运行时没有关系)
变量捕获:作为lambda或者匿名内部类,都能捕获到外面一层作用域中的变量名,就可以使用的。
变量捕获:有一个前置条件,就是变量得是final或者"事实"final,这样才能被捕获的,否则就不能被捕获。
isRunning此处不能报错,不能捕获的原因是:isRunning在下面被更改为了false,并不能“事实”final,所以不能被捕获。
解决方法:将下面isRunning的修改删除,此段代码就不会报错了。但是就达不到控制终止程序的效果。
interrupt、isInterrupted方法终止线程代码
1、interrupt():不是唤醒方法,只是提醒线程终止。
能够设置 线程内置的标志位boolean变量的值;
除了能设置boolean值,还可以唤醒sleep等阻塞的方法;
2、isInterrupted(boolean): 线程内置的标志位boolean,true表示线程终止;false表示线程继续执行。
3、currentThread(): Thread类中的一个static方法,此方法是获取当前线程,能够获取到当前thread这个引用。
在下面catch代码中有重要内容!!!
java
/**
* Thread提供的interrupt()方法和isInterrupted()方法实现控制终止程序
* 1、interrupt():不是唤醒方法,只是提醒线程终止。
* 能够设置 线程内置的标志位boolean变量的值;
* 除了能设置boolean值,还可以唤醒sleep等阻塞的方法;
*
*/
public class thread_isInterrupted_method {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
/**
* currentThread(): Thread类中的一个static方法,此方法是获取当前线程,能够获取到当前thread这个引用。
* isInterrupted(boolean): 线程内置的标志位boolean,true表示线程终止;false表示线程继续执行。
*/
System.out.println("线程任务");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// throw new RuntimeException(e);
e.printStackTrace();
/**
* // 打印异常信息后还能继续线程,线程并没有终止
*
* 导致这个现象的原因是:
* 上述代码中有sleep()方法,线程正在sleep时,
* 触发了interrupt()方法,就导致sleep()方法被唤醒,
* 唤醒的同时就会清除刚才改变的标志位(就又回到了false);
*/
/**
* 是否要结束当前线程,看程序员如何写:
* 1、不想结束当前线程:那么就不写退出循环的代码;
* 2、想结束当前线程:break; // 就会直接结束当前线程
*/
}
}
System.out.println("线程已结束");
});
thread.start();
try {
Thread.sleep(3000);
// 3秒后结束线程
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
// 改变线程内置的标志位boolean值
thread.interrupt();
// 使用interrupt()后,要不要结束线程都是线程自身决定的
}
}