Java中Thread类的基本使用

Thread类的基本用法:

1.创建子类,继承自Thread并且重写run方法:

class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("hello thread");
    }
}
public class Demo1 {
    public static void main(String[] args) {
        // 最基本的创建线程的办法.
        Thread t = new MyThread();
        //调用了start方法才是真正的在系统中创建了线程,执行run方法
        t.start();
    }
}

2.创建一个类,实现Runnable接口再创建Runnable是实例传给Thread

class MyRunnable implements Runnable{
    @Override
    public void run() {
        System.out.println("hello");
    }
}
public class Demo3 {
    public static void main(String[] args) {
        Thread t = new Thread(new MyRunnable());
        t.start();
    }
}

3.匿名内部类

创建了一个匿名内部类,继承自Thread类,同时重写run方法,再new出匿名内部类的实例

public class Demo4 {
    public static void main(String[] args) {
        Thread t = new Thread(){
            @Override
            public void run() {
                System.out.println("hello");
            }
        };
        t.start();
    }
}

new的Runnable,针对这个创建的匿名内部类,同时new出的Runnable实例传给Thread的构造方法

public class Demo5 {
    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello");
            }
        });
        t.start();
    }
}

4.lambda表达式 lambda代替Runnable

public class Demo6 {
    public static void main(String[] args) {
        Thread t = new Thread(() ->{
            System.out.println("hello");
        });
        t.start();
    }
}

线程的一些指标:

1.isDaemon();是否后台线程
后台线程不影响进程退出,不是后台线程会影响进程退出

2.isAlive();是否存活
在调用start前系统中是没有对应线程的,run方法执行完后线程就销毁了,t对象可能还存在

3.isinterrupted();是否被中断

run和start的区别 run单纯的只是一个普通方法描述了任务的内容 start则是一个特殊的方法,内部会在系统中创建线程

中断线程

线程停下来的关键是要让对应run方法执行完,对于main线程来说main方法执行完了才会终止

1.手动设置标志位 在线程中控制这个标志位就能影响到这个线程结束,但是此处多个线程共用一片虚拟空间,因此main线程修改的isQuit和t线程判断的isQuit是同一个值

public class Demo10 {
    // 通过这个变量来控制线程是否结束.
    private static boolean isQuit = false;

    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            while (!isQuit) {
                System.out.println("hello thread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();

        // 就可以在 main 线程中通过修改 isQuit 的值, 来影响到线程是否退出
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // main 线程在 5s 之后, 修改 isQuit 的状态.
        isQuit = true;
    }
}

2.使用Thread中内置的一个标志位来判定 Thread.interruted()这是一个静态方法 Thread.currentThread().isInterrupted()这是一个实例方法,其中currentThread能够获取到当前线程的实例

public class Demo7 {
    public static void main(String[] args)  {
        Thread t = new Thread(() -> {
            while(!Thread.currentThread().isInterrupted()){
                System.out.println("hello");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    // 当触发异常之后, 立即就退出循环~
                    System.out.println("这是收尾工作");
                    break;
                }
            }
        });
        t.start();
        try{
            Thread.sleep(5000);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        // 在主线程中, 调用 interrupt 方法, 来中断这个线程.
        // t.interrupt 的意思就是让 t 线程被中断!!
        t.interrupt();
    }
}

需要注意的是调用这个方法t.interrupt()可能会产生两种情况:
1)如果t线程处在就绪就设置线程的标志位为true
2)如果t线程处在阻塞状态(sleep),就会触发一个InterruptExeception

线程等待

多个线程之间调度顺序是不确定的,有时候我们需要控制线程之间的顺序,线程等待就是一种控制线程执行顺序的手段,此处的线程等待只要是控制线程结束的先后顺序。
哪个线程中的join,哪个线程就会阻塞等待直到对应的线程执行完毕为止。

t.join();
调用这个方法的线程是main线程,针对t这个对象调用的此时就是让main等待t。
代码执行到join这一行就停下了,让t先结束然后main继续。

t.join(10000);
join提供了另一个版本为带一个参数的,参数为等待时间10s之后join直接返回不再等待

Thread.currentThread()

能够获取当前线程的应用,哪个线程调用的currentThread就获取到哪个线程的实例 对比this如下:

对于这个代码来说,通过继承Thread的方法来创建线程。此时run方法中直接通过this拿到的就是当前Thread的实例

public class Demo4 {
    public static void main(String[] args) {
        Thread t = new Thread(){
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
                System.out.println(this.getName());
            }
        };
        t.start();
    }
}

然而此处this不是指向Thread类型,而是指向Runnable,Runnable只是一个单纯的任务没有name属性,要想拿到线程名字只能通过Thread.currentThread()

public class Demo5 {
    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                //err
                //System.out.println(this.getName());
                //right
                System.out.println(Thread.currentThread().getName());
            }
        });
        t.start();
    }
}

你可能感兴趣的:(Java,java,开发语言)