【Java】多线程--Thread类基本用法

Thread类是Java中的一个封装类,用于实现多线程操作,下面是Thread类一些基本用法

1.线程创建

1.1继承Thread类

  1.  继承Thread类,重写run方法,将要执行的语句写进run方法里
    class MyThread extends Thread{
        @Override
        public void run() {
            //下为执行语句
            System.out.println("override run method.");  
        }
    }
    
    public class TestDemo1 {
        public static void main(String[] args) {
            MyThread myThread = new MyThread();   //实例化对象
            myThread.start();                     //start启动线程
        }  
    }
  2.  使用匿名内部类,创建Thread子类对象
    public class TestDemo3 {
        public static void main(String[] args) {
            Thread thread = new Thread(){
                @Override
                public void run() {
                    System.out.println("this is a thread.");
                }
            };
            thread.start();
        }
    }

1.2实现Runnable接口

  1.  实现Runnable接口,重写run方法
  2.  使用匿名内部类,创建Runnable子类对象
    class MyRunnable implements Runnable{
        @Override
        public void run() {
            System.out.println("Runnable implement.");
        }
    }
    
    public class TestDemo2 {
        public static void main(String[] args) {
            Thread thread = new Thread(new MyRunnable());    //实例化Thread,传入参数为新的Runnable对象
            thread.start();                                  //执行线程
        }
    }
    
    public class TestDemo4 {
        public static void main(String[] args) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("this is a thread.");
                }
            });
            thread.start();
        }
    }

 Thread中常见的构造方法:

方法
Thread()创建线程对象
Thread(Runnable target)使用Runnable对象创建线程对象
Thread(String name)创建线程对象并命名
Thread(Runnable target,String name)使用Runnable对象创建线程对象并命名

如:

Thread t1 = new Thread();
Thread t2 = new Thread(new MyRunnable());
Thread t3 = new Thread("Thread name1");                  //命名
Thread t4 = new Thread(new MyRunnable(), "Thread name2");//命名

2.线程中断

线程一旦执行,在线程内代码执行结束前就不会停止,若执行过程中需要线程停止运行,就要通过线程中断的方法来完成,通常中断的方式有两种

  • 共享的标志位
private static class TestFlag implements Runnable{
    public volatile boolean flag = false;
    @Override
    public void run() {       //重写run方法
        while(!flag){
            System.out.println("Thread is running.");
            try {
                Thread.sleep(1000);                //每次循环休眠1秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("Thread is interrupted.");    //线程中断后跳出循环输出
    }
}

public static void main(String[] args) throws InterruptedException {
    TestFlag testFlag = new TestFlag();
    Thread thread = new Thread(testFlag,"aThread");    //新建线程

    System.out.println("start a thread:" + Thread.currentThread().getName());

    thread.start();        //线程运行
    Thread.sleep(5000);    //主线程休眠5秒

    testFlag.flag = true;        //修改标志
}

设置标志为flag,通过判断flag 来决定线程是否继续运行,上述代码在修改标志位flag后,便停止运行跳出循环了

 在使用公共标志位的时候需注意,在多线程的代码中,标志位必须用volatile关键字修饰 

 因为多线程的环境下,volatile才能保证关键字的代码可见性,保证代码的运行准确

  • 通过interrupt()方法

Thread类里包含了一个布尔类型的变量作为线程是否被中断的标记

可以用Thread.interrupted()Thread.currentThread.isInterrupted()代替自定义标志位

public class TestDemo {
    private static class Test implements Runnable{
        @Override
        public void run() {
            //下面也可以用Thread.interrupted()
            while(!Thread.currentThread().isInterrupted()){
                System.out.println("Thread is running.");
                try {
                    Thread.sleep(1000);     //休眠一秒
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    System.out.println("Interrupted!");    //中断后输出
                    break;                                 //跳出循环
                }
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Test test = new Test();
        Thread thread = new Thread(test,"threadName");        //创建线程
        System.out.println(Thread.currentThread().getName()+" start");

        thread.start();            //开始线程
        Thread.sleep(5000);

        thread.interrupt();   //设置标志位,中断线程
    }
}

结果如下,可见代码运行5秒后,修改了标志位,线程就中断了

 上面的中断用到了interrput()方法,常用的中断方法如下

方法说明
public void interrupt()中断对象关联的线程,如果线程正在阻塞,则以异常方式通知
否则设置标志位
public static boolean
interrupted()
判断当前线程的中断标志位是否设置,调用后清除标志位
public boolean
isInterrupted()
判断对象关联的线程的标志位是否设置,调用后不清除标志位

thread收到通知通常有两种情况:

  1. 线程因调用wait(),join()或sleep()等方法而阻塞,则以InterruptedException异常的形式通知,并清除中断标志,此时线程会执行catch里的内容,而线程是否中断则取决于catch中代码的写法,可选择忽略异常,也可以选择跳出循环,如上述例子就是在捕捉异常后通过break跳出循环的
  2. 若没有调用上述方法,只是内部的一个中断标志位被设置,则thread可以通过Thread.interrupted()Thread.currentThread().interrupted()判断指定线程的中断标志,其中前者会清除中断标志,后者不会清除

标志位是否被清除:

  • Thread.interrupted()方法在使用后是会自动清除标志位的,即在判断完后就回到原状态
    private static class MyRunnable implements Runnable{
        @Override
        public void run() {
            //循环5次输出状态
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.interrupted());   //输出状态
            }
        }
    }

    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable,"t1");

        thread.start();      //线程开始
        thread.interrupt();  //中断线程,然后清除标志位

    }

结果:标志位被修改后就被清除了,所以只有第一次输出的是true

  • Thread.currentThread(),isInterrupted()方法在使用后不会清除标志位
        private static class MyRunnable implements Runnable{
            @Override
            public void run() {
                //循环5次输出状态
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().isInterrupted());
                }
            }
        }
    
        public static void main(String[] args) {
            MyRunnable myRunnable = new MyRunnable();
            Thread thread = new Thread(myRunnable,"name");
    
            thread.start();      //线程开始
            thread.interrupt();  //线程中断
        }

    结果:在第一次标志位被修改后输出为true,之后因为标志位未被清除,所以输出依旧为true

3.线程等待

在多线程的使用中,我们常常需要等待其他线程执行完后再开始执行自己的线程,这就涉及到线程等待的问题

线程等待我们使用的方法是join():

public void join()等待线程结束
public void join(long millis)等待线程结束,最多等待millis毫秒
public void join(long millis,int nanos)精度到纳秒级

thread.join(),就是让其他线程等待直至thread线程执行结束

4.线程休眠

线程休眠使用的是Thread的类方法sleep()

public static void sleep(long millis) 休眠当前线程至少milli毫秒

public static void sleep(long millis,int nanos)

精度至纳秒级

注意,在使用sleep放法的时候,进行异常处理

因为线程调度的不可控性,所以该方法的休眠时间是大于等于参数设置的时间的

5.获取当前线程的引用

当多线程运行时,你想知道现在运行的线程是哪个,就可以用Thread的类方法

Thread.currentThread()来返回这个线程的引用

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值