Thread类的基本用法

目录

1.线程创建

2.线程中断

3.线程等待

4.线程休眠

5.获取线程实例


一.线程创建 start()

1.创建实例

(1)继承Thread 重写run();

class MyThread extends Thread{
    public void run(){
        while(true){
            System.out.println("hello thread");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public class demo1 {
    public static void main(String[] args) {
        Thread t = new MyThread();//向上转型;
        t.start();
        while(true){
            System.out.println("hello main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

(2)实现Runnable 重写run(); 

class MyRunnable implements Runnable{
    public void run(){
        while(true){
            System.out.println("hello thread");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public class demo2 {
    public static void main(String[] args) {
        Runnable runnable = new MyRunnable();
        Thread r = new Thread(runnable);
        r.start();
        while(true){
            System.out.println("hello main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

(3)继承Thread 重写run() 使用匿名内部类;

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

(4)实现Runnable 重写run() 使用匿名内部类;

public class demo4 {
    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                while(true){
                    System.out.println("hello thread");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        Thread t = new Thread(runnable);
        t.start();
    }
}

(5)使用lambda表达式;(最推荐的方法!)

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

创建实例不等于在操作系统内核中创建出了线程,只有调用了start()才是真正的创建出线程。

二.线程中断

线程执行结束:只要让入口方法(main方法)执行完了,线程就随之结束。

(1)直接使用标志位来区分线程是否结束

public class demo9 {
    //用boolean变量标识线程是否结束;
    private static boolean isQuit = false;
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(()->{
            //此时与直接写while(true)并没有什么区别;
            while(!isQuit){
                System.out.println("线程正在运行中!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("新线程执行结束!");
        });
        t.start();
        Thread.sleep(1000);
        System.out.println("控制新线程退出!");
        //将isQuit置为true,则不进入上述循环中,新线程退出!
        isQuit = true;
    }
}

(2)使用Thread自带的标志位进行区分

interrupt方法的行为:1.如果 t 线程没有处于阻塞状态,interrupt就会修改内置的标志位;2.如果 t线程处于阻塞状态,interrupt就会触发sleep InterruptException;

当线程处于阻塞状态时,借助catch有三种解决方式:立即退出;等一会退出;不退出。

public class demo10 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(()->{
            while(! Thread.currentThread().isInterrupted()){
                System.out.println("线程运行中!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    //立即退出;
                    //break;
                    //等一会退出,sleep可以换成任意的收尾代码;
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                    break;//等一会退出;
                    //不退出,啥都不做,忽略异常;
                }
            }
            System.out.println("新线程已经退出!");
        });
        t.start();
        Thread.sleep(1000);
        System.out.println("新线程退出!");
        t.interrupt();
    }
}

除Thread.currentThread().isInterrupted(),还可以使用Thread.interrupt(),不同的是Thread.currentThread().isInterrupted()不会自动清除,而Thread.interrupt()标志位会自动清除,控制它中断后标志位会先设为true,读取的时候会读到这true,但是读完之后这个标志位会自动恢复成false。

三.线程等待 join()

线程之间的执行顺序是完全随机的,由系统的调度决定,此时可以通过join()来控制线程的结束顺序。例如:无法干预调度器的行为,则可以让main线程主动进行等待,即在main线程中调用t1.join()和t2.join(),main阻塞等待t1,t2执行完,main接触阻塞,才能往下执行。

join()方法的行为:1.如果被等待的线程还没执行完,就阻塞等待;2.如果被等待的线程已经执行为了,直接就返回。

public void join() 等待线程结束(死等,没有时间限制);public void join(long millis)等待线程结束,最多等mills毫秒;public void join(long millis,int nanos) 同理,但具有更高精度。

public class demo11 {
    //main线程等待t2线程,t2线程等待t1;
    private static Thread t1 = null;
    private static Thread t2 = null;
    public static void main(String[] args) throws InterruptedException {
        System.out.println("main begin");
        t1 = new Thread(()->{
            System.out.println("t1 begin");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("t1 end");
        });
        t1.start();
        t2 = new Thread(()->{
            System.out.println("t2 begin");
            try {
                t1.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("t2 end");
        });
        t2.start();
        t2.join();
        System.out.println("main end");
    }
}

四.线程休眠 sleep()

线程调用sleep()后,会由就绪队列进入阻塞队列,要等到sleep()时间结束,结束后由阻塞队列进入就绪队列,进入就绪队列后可上CPU执行,但是什么时候能上CPU执行的时间不能确定,由系统调度器决定。(PCB是一个双向链表)

五.获取线程实例 currentThread() 

为了对线程进行操作(线程等待,线程中断,获取线程属性等),就需要获取到线程引用。如果该线程继承Thread,然后重写run方法,可以直接在run中使用this获取线程实例,但如果使用Runnable或者lambda时,就要使用Thread.currentThread()。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值