线程的常用方法
1.1 currentThread()方法(类方法)
Thread.currentThread()方法可以获得当前线程
Java 中的任何一段代码都是执行在某个线程当中的.。执行当前代 码的线程就是当前线程。
同一段代码可能被不同的线程执行, 因此当前线程是相对 的,Thread.currentThread()方法的返回值是在代码实际运行时候的线 程对象。
代码:
public class MyThread extends Thread {
public MyThread() {
System.out.println(" 构 造 方 法 打 印 当 前 线 程 的 名 称 : " +
Thread.currentThread().getName());
}
@Override
public void run() {
System.out.println("run 方 法 打 印 当 前 线 程 名 称 :" +
Thread.currentThread().getName());
}
}
测试代码:
public class Test {
public static void main(String[] args) {
System.out.println("main 方 法 中 打 印 当 前 线 程 :"
+Thread.currentThread().getName());
//创建子线程, 调用 MyThead()构造方法, 在 main 线程中调用构造方法,所以构造
//方法中 的当前线程就是 main 线程
MyThread t1 = new MyThread();
t1.start(); //启动子线程,子线程会调用 run()方法,所以 run()方法中 的当
//前线程就是 Thread-0 子线程
}
}
结果:
结论:
创建子线程, 调用 MyThead()构造方法, 在 main 线程中调用构造方法,所以构造方法中 的当前线程就是 main 线程
启动子线程,子线程会调用 run()方法,所以 run()方法中 的当前线程就是 Thread-0 子线程
1.2 setName()/getName()(实例方法)
thread.setName(线程名称), 设置线程名称。
thread.getName()返回线程名称 。
通过设置线程名称,有助于程序调试,提高程序的可读性, 建议为 每个线程都设置一个能够体现线程功能的名称
代码:
public class MyThread extends Thread {
@Override
public void run() {
System.out.println("run 方 法 打 印 当 前 线 程 名 称 :" +
Thread.currentThread().getName());
}
}
测试代码:
public class Test {
public static void main(String[] args) {
MyThread thread=new MyThread();
thread.setName("帅气的线程");//设置线程名称,记得一定要在线程启动时设置
thread.start();
}
}
结果:
1.3 isAlive() (实例方法)
thread.isAlive()判断当前线程是否处于活动状态。
活动状态就是线程已启动并且尚未终止。
代码:
public class MyThread extends Thread {
@Override
public void run() {
//运行状态,true
System.out.println("run 方法, isalive = " + this.isAlive());
}
测试代码:
public class Test {
public static void main(String[] args) {
MyThread t3 = new MyThread();
System.out.println("begin==" + t3.isAlive()); //false,在启动线程之前
t3.start();
System.out.println("end==" + t3.isAlive());
//结果不一定,打印这一行时,如果 t3线程还没结束就返回 true, 如果 t3 线程已结束,返回 false
}
}
结果:
1.4 sleep() (类方法)
Thread.sleep(millis):让当前线程休眠指定的毫秒数
当前线程是指 Thread.currentThread()返回的线程
代码:
public class Mythread2 extends Thread {
@Override
public void run() {
//给定60s时间
int m=60;
while(true){
System.out.println(m);
//相当于时间-1;
m--;
if (m<0){
break;
}
//让线程没执行一次循环就休眠一秒
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
测试代码:
public class Test2 {
public static void main(String[] args) {
//创建线程
Mythread2 mythread2=new Mythread2();
mythread2.start();//启动线程
}
}
结果:每秒减1
实例方法)
thread.getId()可以获得线程的唯一标识
注意:
某个编号的线程运行结束后,该编号可能被后续创建的线程使用
重启的 JVM 后,同一个线程的编号可能不一样
代码:
public class MyThread extends Thread {
@Override
public void run() {
System.out.println("thread name = " + Thread.currentThread().getName()
+ ", id == " + this.getId() );
}
}
测试代码:
public class Test2 {
public static void main(String[] args) {
//查看主线程id
System.out.println( Thread.currentThread().getName() + " , id = "
+Thread.currentThread().getId());
//循环5次,创建5个子线程, 查看不同子线程的 id
for(int i = 1; i <= 5; i++){
new MyThread().start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
结果:
1.6 yield() (类方法)
Thread.yield()方法的作用是放弃当前的 CPU 资源
代码:
public class MyThread extends Thread {
@Override
public void run() {
long begin = System.currentTimeMillis();
long sum = 0;
for(int i = 1; i <= 1000000; i++){
sum += i;
Thread.yield(); //线程让步, 放弃 CPU 执行权
}
long end = System.currentTimeMillis();
System.out.println("子线程用时: " + (end - begin));
}
}
测试代码:
public class Test {
public static void main(String[] args) {
//创建子线程并启动,开始计算累加
MyThread myThread=new MyThread();
myThread.start();
//在 main 线程中计算累加和
long begin = System.currentTimeMillis();
long sum = 0;
for(int i = 1; i <= 1000000; i++){
sum += i;
}
long end = System.currentTimeMillis();
System.out.println("main 方法 , 用时: "+(end-begin));
}
结果:
结论:
在代码中,main方法线程和子线程都进行了累加计算,但是,由于子线程的run()中使用了 Thread.yield()方法,导致子线程每执行一次累加,就要放弃其拥有的cpu资源,然后再进行排队,等待cpu分配资源,所以导致计算完累加耗时比较大 。
1.7 setPriority()(实例方法)
thread.setPriority( num ); 设置线程的优先级。
java 线程的优先级取值范围是 1 ~ 10 , 默认的优先级是5,如果超出这个范围会抛出异常 IllegalArgumentException。
在操作系统中,优先级较高的线程获得 CPU 的资源越多。
线程优先级本质上是只是给线程调度器一个提示信息,以便于调 度器决定先调度哪些线程. 注意不能保证优先级高的线程先运行。
Java 优先级设置不当或者滥用可能会导致某些线程永远无法得到运行,即产生了线程饥饿。
线程的优先级并不是设置的越高越好,一般情况下使用普通的优 先级即可,即在开发时不必设置线程的优先级。
线程的优先级具有继承性, 在 A 线程中创建了 B 线程,则 B 线程的 优先级与 A 线程是一样的。
由于创建线程比较少,设置了看不出区别,所以这里不用代码演示了。
1.8 interrupt()(实例方法)
中断线程.。
注意调用 interrupt()方法仅仅是在当前线程打一个停止标志,并不是真正的停止线程
代码:
public class MyThread extends Thread {
@Override
public void run() {
for (int i=0;i<10000;i++){
if (this.isInterrupted()){
System.out.println("当前线程的中断标志为 true, 我要退出了");
break; //中断循环, run()方法体执行完毕,
}
System.out.println("子线程——》"+i);
}
}
}
测试代码:
public class Test {
public static void main(String[] args) {
MyThread t1 = new MyThread();
t1.start(); //开启子线程
//当前线程是 main 线程
for(int i = 1; i<=1000; i++){
System.out.println("main ==> " + i);
}
//中断子线程
t1.interrupt(); //仅仅是给子线程标记中断,让子线程里面的isInterrupted()去识别
}
}
结果:
结论:
interrupt()方法仅仅是在当前线程打一个停止标志,并不是真正的停止线程,要想让线程真正的停止,必须要搭配线程的另一个捕获方法isInterrupted(),它用来判断当前线程是否被打了中断停止标志,有就放回布尔值true 没有就是false。
1.9 setDaemon()(实例方法)
Java 中的线程分为用户线程与守护线程
守护线程是为其他线程提供服务的线程,如垃圾回收器(GC)就是一 个典型的守护线程
守护线程不能单独运行, 当 JVM 中没有其他用户线程,只有守护线程时,守护线程会自动销毁, JVM 会退出。
代码:
public class MyThread extends Thread {
@Override
public void run() {
//使用死循环,只有线程销毁时才会停止
while(true){
System.out.println("sub thread.....");
}
}
}
测试代码:
public class Test {
public static void main(String[] args) {
MyThread t1 = new MyThread();
//将当前线程设置为守护线程
t1.setDaemon(true);
t1.start(); //开启子线程
//当前线程为 main 线程
for(int i = 1; i <= 10000 ; i++){
System.out.println("main== " + i);
}
//当 main 线程结束, 守护线程 thread 也销毁了
}
}
结果:
结论:
守护线程是可以人为设置的,而且它不能单独运行,当其他用户线程结束时,守护线程也会被销毁