Thread的基本方法

目录

线程的创建

线程中断

线程等待

线程休眠

获取线程实例


线程的创建

a.继承Thread类,覆写run方法(线程的核心工作任务方法)

(最终启动线程都是通过Thread类的start启动线程)

1.一个子类继承Thread类

2.覆写run方法

3.产生当前子类对象,而后调用start方法启动线程

调用start方法启动线程,是由JVM产生操作系统的线程并启动,到底啥时候真正启动,对我们来说是不可见的,没发控制

当线程已经启动之后再次调用该线程的start方法会抛出非法线程状态异常,说明该线程已经启动过了

b.覆写Runnable接口,覆写run方法

(最终启动线程都是通过Thread类的start启动线程)

1.实现了Runnable接口的子类,并不是直接的线程对象,只是一个线程的核心工作任务

实现了Runnable接口更加灵活,子类还能实现别的接口没继承别的类,

方式a只能继承Thread - 单继承局限

关于方式a和方式b的不同写法

1.使用匿名内部类创建Thread对象

使用匿名内部类实现Runnable接口

2.使用lambda表达式实现Runnable接口

c.覆写Callable接口,覆写call方法

d.使用线程池创建线程

 

线程中断

中断一个正在执行的线程(run方法还没有执行结束),普通线程会在run方法执行结束之后自动停止,

Thread类的所有静态方法都是 在哪个线程中调用的,就生效在哪个线程

线程收到内置的中断通知有两种方式:

a.通过共享变量进行中断

b.使用Thread.interrupted()静态方法或者 Thread 对象的成员方法isInterrupted

Thread类的内部包含了一个属性,当前线程是否被中断属性

当线程调用sleep/wait/join等方法处在阻塞状态时,收到中断通知

1.Thread.inerrupt();判断当前线程是否中断,若中断状态为true,清楚中断标志

2.Thread.currentThread.isInterrupted();判断指定线程对象时候状态为中断状态,若状态为true,不清除中断标志

3.调用线程对象的 Interrupt方法就会将指的线程对象状态置为中断状态

a.若该线程在run方法正在执行,sleep,wait,join处正在等待状态,调用interrupt方法当前线程就会抛出中断异常,捕获这个中断异常决定线程是否退出(结束run方法就退出了),一旦抛出中断异常,无论调用哪种判断方法,中断状态都会 还原

b.若该线程处在普通的run方法中,没有进入等待状态,则调用interrupt方法只是将线程的中断属性置为true而已。

线程等待

线程等待与唤醒机制。wait和notify是Object类的方法,用于线程的等待与唤醒,必须搭配synchronized锁来使用

多线程并发的场景下,有时需要某些线程先执行,这些线程执行结束后其他线程再继续执行

wait() 方法:
wait方法是Object类提供的方法,需要搭配synchronized锁来使用,调用wait方法会释放锁,线程进入阻塞状态,等待被其他线程唤醒或者超时自动唤醒,唤醒之后的线程需要再次竞争synchronized锁才能继续执行

wait 结束等待的条件 :
其他线程调用该对象的 notify 方法 .
wait 等待时间超时 (wait 方法提供一个带有 timeout 参数的版本 , 来指定等待时间 ).
其他线程调用该等待线程的 interrupted 方法 , 导致 wait 抛出 InterruptedException 异常 .
notify()方法:
notify 方法是唤醒等待的线程 .
方法 notify() 也要在同步方法或同步块中调用,该方法是用来通知那些可能等待该对象的对象锁的
其它线程,对其发出通知 notify ,并使它们重新获取该对象的对象锁。
如果有多个线程等待,则有线程调度器随机挑选出一个呈 wait 状态的线程。 ( 并没有 " 先来后到 ")
notify() 方法后,当前线程不会马上释放该对象锁,要等到执行 notify() 方法的线程将程序执行
完,也就是退出同步代码块之后才会释放对象锁。
notifyAll():唤醒所有处在等待状态的线程
对于wait和notify方法,其实有一个阻塞队列和一个等待队列

阻塞队列

阻塞队列一种特殊的队列,则遵循“先进先出”的原则

阻塞队列是一种线程安全的的数据结构,并且具有以下特性:

a.入队时,若队列已满,则入队操作会"阻塞",直到有其他线程从队列中取出元素;

b.出队时,若队列为空,则出队操作会"阻塞",直到有其他线程向队列中添加元素

阻塞队列表示同一时间只有一个线程能获取锁,其他线程进入阻塞队列

等待队列表示调用wait(首先此线程要获取到锁,进入等待队列,释放对象锁 )

JDK中的阻塞队列BlockingQueue,入队方法put()阻塞式入队方法,出队方法

take()阻塞式的出队

常用子类 ArrayBlockQueue、LinkedBlockQueue

线程休眠

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

sleep()方法:

休眠当当前线程

Thread.sleep(long millis):在哪里调用,就休眠那个线程

sleep方法是Thread类提供的方法,调用sleep方法的线程进入TIME_WAITING状态,不会释放锁,时间到自然唤醒

获取线程实例

继承Thread类,覆写run方法

private static class MyThread extends Thread{
        @Override
        public void run() {
            Random random = new Random();
            while (true){
                System.out.println(Thread.currentThread().getName());
                try {
                    Thread.sleep(random.nextInt(10));
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }

        public static void main(String[] args) {
            MyThread m1 = new MyThread();
            MyThread m2 = new MyThread();
            MyThread m3 = new MyThread();

            m1.start();
            m2.start();
            m3.start();

            Random random = new Random();
            while (true){
                System.out.println(Thread.currentThread().getName());
                try {
                    Thread.sleep(random.nextInt(10));
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

覆写Runnable接口,覆写run方法

public class RunnableMethod implements Runnable{

    @Override
    public void run() {
        System.out.println("这是Runnable方式实现的子线程任务");
    }
}

使用线程池创建线程

public static void main(String[] args) {
        // 固定大小线程池
        ExecutorService pool = Executors.newFixedThreadPool(10);
        // 数量动态变化的缓存池
        ExecutorService pool1 = Executors.newCachedThreadPool();
        // 只包含一个线程的单线程池
        ExecutorService pool2 = Executors.newSingleThreadExecutor();
        // 定期线程池,可以设置任务的延时启动时间(Timer类的线程池实现)
        // 定时器线程池
        ScheduledExecutorService pool3 = Executors.newScheduledThreadPool(10);
        pool2.submit(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().getName() + " hello~" + i);
                }
            }
        });
        pool3.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + " 3s后执行此任务");
            }
        },3, TimeUnit.SECONDS);
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值