1.3.2 setName()/getName()
thread.setName(线程名称),设置线程名称 thread.getName() 返回线程名称 通过设置线程名称有有助于程序的调试,提高程序的可读性,建议为每个线程都设置一个能够体现线程功能的名称
1.3.3isAlive()
thread.isAlive判断当前线程是否处于活动状态。 活动状态:线程以启动并且未终止
主线程
public class Test {
public static void main(String[] args) {
SubThread subThread = new SubThread();
//启动相册线程之前false
System.out.println("begin=="+subThread.isAlive());
subThread.start();
//这个的结果不一定如果子线程结束就会返回false,如果结束就会返回true
System.out.println("end=="+subThread.isAlive());
}
}
子线程
public class SubThread extends Thread {
@Override
public void run() {
System.out.println("run方法,isAlive"+this.isAlive());
}
}
运行结果
begin==false
end==true //这个结果不一定
run方法,isAlivetrue
1.3.4 sleep()
Thread.sleep(millis);让当前线程休眠指定的毫秒数 当前线程是指Thread.currentThread()返回的线程 主线程
public class Test {
public static void main(String[] args) {
SubThread subThread = new SubThread();
System.out.println("main_begin="+System.currentTimeMillis());
subThread.start();
System.out.println("main_end="+System.currentTimeMillis());
}
}
子线程
public class SubThread extends Thread{
@Override
public void run() {
System.out.println("run threadname="+Thread.currentThread().getName()+"begin="+System.currentTimeMillis());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
//在子线程的run方法中,如果有受检异常(编译时异常)需要处理,只有选则捕获异常,不能抛出处理
e.printStackTrace();
}
System.out.println("run threadname="+Thread.currentThread().getName()+"end="+System.currentTimeMillis());
}
}
运行结果
main_begin=1660491805852
main_end=1660491805852
run threadname=Thread-0begin=1660491805853
run threadname=Thread-0end=1660491808854
简易的计时器
/*
* 使用线程休眠Thread.sleep完成一个简易的计时器
* */
public class SimpleTimer {
public static void main(String[] args) {
int remaining = 60;//从60秒开始计时
//读取main方法的参数
if(args.length == 1){
remaining =Integer.parseInt(args[0]);
}
while (true){
System.out.println("Remaining:"+remaining);
remaining--;
if(remaining<0){
break;
}
try {
Thread.sleep(1000); //线程休眠
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Done!!!");
}
}
1.3.5 getId()
thread.getId()可以获得线程的唯一标识
注意: 某个编号的线程运行结束后,该编号可能被后续创建的线程使用。 重启JVM后,同一个线程可能不一样
主线程
public class Test {
public static void main(String[] args) {
System.out.println("main name = "+Thread.currentThread().getName());
System.out.println( "id =="+ Thread.currentThread().getId());
//子线程的id
for (int i = 0; i < 3; i++) {
new SubThread().start();
}
}
}
子线程
public class SubThread extends Thread{
@Override
public void run() {
System.out.println("thread name = "+Thread.currentThread().getName());
System.out.println( "id =="+ this.getId());
}
}
运行结果
main name = main
id ==1
thread name = Thread-0
id ==12
thread name = Thread-1
id ==13
thread name = Thread-2
id ==14
1.3.6 yield()
Thread.yield()方法的作用是放弃当前的CPU资源
主线程
public class Test {
public static void main(String[] args) {
SubThread subThread = new SubThread();
subThread.start();
long begin = System.currentTimeMillis();
int sum=0;
for (int i = 0; i < 10000000; i++) {
sum=+i;
}
long end = System.currentTimeMillis();
System.out.println("main用时"+(end-begin));
}
}
子线程
public class SubThread extends Thread {
@Override
public void run() {
long begin = System.currentTimeMillis();
int sum=0;
for (int i = 0; i < 10000000; i++) {
sum=+i;
Thread.yield();//线程让步,放弃CPU执行权
}
long end = System.currentTimeMillis();
System.out.println("用时"+(end-begin));
}
}
运行结果,如果子线程不让步的话,两个线程用时会差不多
main用时1
用时8505
1.3.7 setPrioriy()
thread.setPriority(num);设置线程的优先权
java线程的优先权取值范围是1~10如果超出这个范围会抛出异常
在操作系统中,优先级较高的线程获得CPU的资源越多
线程优先级本质上是只是给线程调度器一个提示信息,以便于调度器决定先调度那些线程,
注意不能保证优先级高的线程先运行
Java优先级设置不当或者滥用可能会导致某些线程永远无法得到运行,即产生了线程饥饿。
线程的优先级并不是设置的越高越好,一般情况下使用普通的优先级即可,即在开发时不必设置线程的优先级
线程的优先级具有继承性,如果在A线程中创建了B线程,则B的优先级与A优先级一样
主线程
public class Test {
public static void main(String[] args) {
SubThread subThread = new SubThread();
subThread.setPriority(1);
SubThreadII subThreadII = new SubThreadII();
subThreadII.setPriority(10);
subThread.start();
subThreadII.start();
}
}
子线程一
public class SubThread extends Thread{
@Override
public void run() {
int sum=0;
for (int i = 0; i < 1000000000; i++) {
sum=+i;
}
System.out.println("子线程一");
}
}
子线程二
public class SubThreadII extends Thread {
@Override
public void run() {
int sum=0;
for (int i = 0; i < 1000000000; i++) {
sum=+i;
}
System.out.println("子线程二");
}
}
运行结果
子线程二
子线程一
1.3.8 interrupt()
中断线程
注意:调用interr()方法仅仅是在当前线程打一个停止标志,并不是真正的停止线程
主线程
public class Test {
public static void main(String[] args) {
SubThread subThread = new SubThread();
subThread.start();//开启子线程
//当前是main线程
for (int i = 0; i < 10; i++) {
System.out.println("main==>"+i);
}
//中断子线程
subThread.interrupt();
}
}
子线程
public class Test {
public static void main(String[] args) {
SubThread subThread = new SubThread();
subThread.start();//开启子线程
//当前是main线程
for (int i = 0; i < 10; i++) {
System.out.println("main==>"+i);
}
//中断子线程
subThread.interrupt();
}
}
运行结果
main==>0
sub==>0
sub==>1
sub==>2
sub==>3
sub==>4
main==>1
main==>2
sub==>5
main==>3
main==>4
main==>5
main==>6
main==>7
main==>8
main==>9
sub==>6
sub==>7
sub==>8
sub==>9
由运行结果我们可以看出,虽然在main线程结束以后使用了 subThread.interrupt();但是子线程并没有结束
我们可以结合isInterrupted()方法来手动中断线程
子线程
public class SubThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
//判断线程的中断标志
if(this.isInterrupted()){
System.out.println("线程中断");
break;//中断循环
}
System.out.println("sub==>"+i);
}
}
}
运行结果
main==>0
main==>1
main==>2
main==>3
main==>4
main==>5
sub==>0
sub==>1
main==>6
main==>7
main==>8
main==>9
sub==>2
线程中断
1.3.9 setDaemon()
java中的线程分为用户线程和守护线程
守护线程是为其他线程提供服务的线程,如垃圾回收器,就是一个典型的守护线程。
守护线程不能单独运行,当一个JVM只剩下守护线程的时候,守护线程就会自动销毁,JVM会退出
主线程
public class Test {
public static void main(String[] args) {
SubDaemonThread subDaemonThread = new SubDaemonThread();
subDaemonThread.setDaemon(true);//设置守护线程的代码要在启动前
subDaemonThread.start();
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
}
}
子线程
public class SubDaemonThread extends Thread {
@Override
public void run() {
while (true){
System.out.println("守护线程");
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
运行结果
0
1
2
3
4
5
6
7
8
9
守护线程
//为什么在主线程结束之后会有守护线程执行?
//因为销毁线程需要时间