Thread 类的一些基本用法

线程的创建

1.创建一个类继承Thread类并重写run方法

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

        while(true){
            System.out.println("hello main!");
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}

2.创建一个类实现Runnable接口,并重写run方法

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

        while(true){
            System.out.println("hello main!");
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

3.使用匿名内部类,创建Thread子类,重写run方法

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

        while(true){
            System.out.println("hello main!");
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

4.new一个Runnable实例传给Thread构造方法,并重写run方法

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

        while(true){
            System.out.println("hello main!");
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

5.使用lambda表达式创建线程

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

        thread.start();

        while(true){
            System.out.println("hello main!");
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}

线程的中断

1.手动设计标记位

我们想要中断一个线程,如果那个线程一直在执行,我们可以在run方法中,手动设定一个标记位,假设默认情况为false,然后线程在执行前任务前都要判断标记位,当我们在主线程中更改标记位为true,此时执行的线程被中断,否则继续执行。

public class Demo {
    public static boolean flag=false;//设定标记
    public static void main(String[] args) throws InterruptedException {
        Thread t1=new Thread(()->{
            while (!flag){
                System.out.println("执行线程任务!");
                try {
                    Thread.sleep(1000);//线程每休眠1s就执行一次
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t1.start();//启动线程
        Thread.sleep(4000);//主线程休眠4s后执行
        flag=true;//更改标记
    }
}

执行结果:

在这里插入图片描述

2.使用Thread对象中得标记位

先调用的是currentThread()方法获取当前线程对象,然后调用该线程对象中的isInterrupted()方法获取标记位,类似我们之前手动设置的flag标记位。线程每次执行任务前都要判断标记位,而我们只需要在main线程中修改标记位就能中断线程的执行。中断线程调用的是interrupted()方法。

public class Demo2 {
    public static void main(String[] args) throws InterruptedException {

        Thread t1=new Thread(()->{
            while (!Thread.currentThread().isInterrupted()){
                System.out.println("线程执行任务!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t1.start();
        Thread.sleep(4000);//主线程休眠
        t1.interrupt();//中断t1线程
    }

}

运行结果:

在这里插入图片描述
和我们预期似乎有差别,线程在执行到了一定时间后,抛出异常后继续执行,并未中断,原因是 因为使用interrupt方法触发中断机制时,如果该线程是Runnable状态则设定标志位,如果该线程是阻塞状态(sleep等),会抛出异常,虽然此时interrupt仍然会设定标志位,但是sleep、wait等方法会清除这个标记位。所以也就是为什么线程会继续执行。此时如果我们还是非要中断该线程,就得在抛出异常时,在catch代码块内,不仅要抛异常,还需要跳出循环执行的线程任务(break即可)。

public class Demo3 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1=new Thread(()->{
            while (!Thread.currentThread().isInterrupted()){
                System.out.println("线程执行任务!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    System.out.println("线程任务结束!");
                    break;
                }
            }
        });
        t1.start();
        Thread.sleep(4000);//主线程休眠
        t1.interrupt();//中断t1线程
    }
}

执行结果:

在这里插入图片描述

3.使用Thread类中的标记位

这是使用Thread类中的静态方法interrupted()也能够访问类中的标记位,而且一般一个程序中只有一个,我们可以用它来作为线程中断的标记位。而修改标记位还是使用interrupt方法来中断线程执行。

public class Demo4 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1=new Thread(()->{
            while (!Thread.interrupted()){
                System.out.println("线程执行任务!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    System.out.println("线程任务结束!");
                    break;
                }
            }
        });
        t1.start();
        Thread.sleep(4000);
        t1.interrupt();//中断t1线程
    }
}

执行结果:

在这里插入图片描述

线程等待

使用join()方法,注意join方法的使用,例如有两个线程,一个线程A,一个线程B,在A中使用B.join(),意思是A线程要等待B线程执行结束后才能执行(A线程阻塞)。同理在B中使用A.join(),意思是B线程要等待A线程执行结束后才能执行(B线程阻塞)。

public class Demo {

    public static final long COUNT=10_000_000_000L;
    
    public static void main(String[] args) {
    
     	long beg=System.currentTimeMillis();
        Thread thread1=new Thread(()->{
            long a=0;
            for (long i = 0; i < COUNT; i++) {
                a++;
            }
        },"这里可以放线程的名字");

        Thread  thread2=new Thread(()->{
            long a=0;
            for (long i = 0; i <COUNT ; i++) {
                a++;
            }
        });

        thread1.start();
        thread2.start();

        try {
            //main线程阻塞,等线程1和线程2执行结束后,main线程才能继续执行
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long end=System.currentTimeMillis();
        System.out.println("并发执行时间:"+(end-beg)+"ms");
       
    }
 
}

线程休眠

使用sleep(long)方法,会使当前调用的该方法的线程休眠一段时间,这段时间内线程处于阻塞等待状态,该时间是自己设定,等一段时间过后,该线程就会继续执行。

public class Demo3 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1=new Thread(()->{
            while (true){
                System.out.println("线程执行任务!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t1.start();

获取线程实例

获取当前线程引用使用 Thread.currentThread()方法,在哪个线程内调用,就是获取哪个线程的引用。之前我们用这个对象引用获取isInterrupted()方法判断当前线程是否是处于中断状态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值