多线程基础

一、创建多线程的方法

  1.通过继承Thread类实现多线程

复制代码
class myThread extends Thread{
    public myThread(String name){
        super(name);
    }

    @Override
    public void run() {
        int i=0;
        while(i++ < 5){
            System.out.println(Thread.currentThread()+" is running");
        }
    }
}
    public static void main(String[] args) {
        //继承Thread实现多线程
        myThread t1 = new myThread("线程1");
        t1.start();
        myThread t2 = new myThread("线程2");
        t2.start();
}
复制代码

  2.Runnable接口实现多线程

Runnable接口只有一个抽象的run方法

复制代码
//使用Runnable接口实现多线程
        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                int i=0;
                while(i++ < 5){
                    System.out.println(Thread.currentThread()+" is running");
                }
            }
        },"线程3");t3.start();
        //lambda表达式
        Thread t4 = new Thread(()-> {
            int i=0;
            while(i++ < 5){
                System.out.println(Thread.currentThread()+" is running");
            }
        },"线程4");t4.start();
复制代码

  3.Callable接口实现多线程

复制代码
//callable接口实现多线程,该方法的好处是有返回值
        FutureTask<Object> ft =new FutureTask<Object>(()->{
            int i=0;
            while(i++ < 5){
                System.out.println(Thread.currentThread()+" is running");
            }
            return 1;
        });
        Thread t5 = new Thread(ft,"进程5");
        t5.start();
        try {
            //得到返回值
            Object result = ft.get();
            System.out.println(result);
        } catch (Exception e) {
            e.printStackTrace();
        }
复制代码

Callable相比于前面两种方法的好处是有返回值

方法声明 功能描述
boolean cancel(boolean mayInterruptIfRunning) 用于取消任务,参数表示是否允许取消正在执行却没有执行完毕的任务,true表示取消可以正在执行的任务
boolean isCancelled() 判断任务是否被成功取消,如果正常完成前被取消,则返回true
boolean isDone() 判断任务是否已经完成,若任务完成返回true
T get 用于获取执行结果,这个任务会发生阻塞,需等到任务执行完毕才返回执行结果
T get(long timeout,TimeUnit unit)

指定时间获取结果,在指定时间没有获取结果,则返回null

二、线程的生命周期及状态转换

当线程任务代码正常执行完毕或者线程抛出一个未捕获的异常(Exception)或者错误(Error)时,线程生命周期便会结束

线程的生命周期分为6个状态,`NEW`(新建状态)、`RUNNABLE`(可运行状态)、`BLOCKED`(阻塞状态)、`WAITING`(等待状态)、`TIMED_WAITING`(定时等待状态)和`TERMINATED`(终止状态)。

1.`NEW`(新建状态)

创建一个线程对象后,该线程对象就处于新建状态,此时不能允许,仅仅由jvm分配内存,没有表现出线程的动态特征

2.`RUNNABLE`(可运行状态)

当线程调用了start方法,此时就会从新建状态转换为可运行状态,`RUNNABLE`(可运行状态)可细分为两个状态:READY(就绪状态)、RUNNABLE(允许状态)

,并且线程可在这两个状态间相互转换

READY(就绪状态):线程对象调用start方法,等待JVM调度,此时线程并没有执行

RUNNABLE(允许状态)线程对象获得JVM调度,如果存在多个CPU,那么就允许多个线程并行运行

3.`BLOCKED`(阻塞状态)

处于运行状态的线程可能会因为某些原因失去CPU的执行权,暂时停止运行进入阻塞状态,此时JVM不会给线程分配CPU,直到线程从新进入就绪状态,才有机会转换到运行状态。阻塞状态只能先进入就绪状态,才能再进入运行状态

线程一般会再两个情况下进入阻塞状态:

1. 当线程A运行过程种,试图获取同步锁,却被B线程获取,此时JVM把当前线程A存放到对象的锁池中,线程A就进入阻塞状态

2. 当线程运行过程中,发出I/O请求时,此时该线程也会进入阻塞状态

4.`WAITING`(等待状态)

当运行状态的线程调用了无时间参数限制后,如wait()、join()等方法就会使处于运行状态的线程转换成等待状态

处于等待状态的线程不能立即抢夺CPU的使用权,必须等待其他线程执行特定的操作后,才有机会再次争夺CPU的使用权,将等待状态的线程转换成运行状态

5、`TIMED_WAITING`(定时等待状态)

将运行状态中的线程转换为定时等待状态中的线程,方法与转换为等待状态类似,只是增加了时间参数

6、`TERMINATED`(终止状态)

线程的run方法、call方法正常执行完毕或者线程抛出一个未捕获的异常或者错误,线程就会进入终止状态,一旦进入终止状态,线程不在拥有运行的资格,也不再转换到其他状态,生命周期结束

三、线程的调度

  1.线程的优先级

 

Thread类的静态窗帘 功能描述
static int MAX_PRIORITY                            表示线程的最高优先级,相当于10                       
static int MIN_PRIORITY 表示线程的最低优先级,相当于1
static int NORM_PRIORITY 表示线程的普通优先级,相当于5
复制代码
Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                int i=0;
                while(i++ < 5){
                    System.out.println(Thread.currentThread()+" "+i);
                }
            }
        },"t1");
        Thread t2 = new Thread(()->{
            int i=0;
            while(i++ < 5){
                System.out.println(Thread.currentThread()+" "+i);
            }
        },"t2");
        //设置优先级
        t1.setPriority(Thread.MAX_PRIORITY);
        t2.setPriority(Thread.MIN_PRIORITY);
        t1.start();
        t2.start();
复制代码

虽然java提供了10个线程优先级,但这些优先级需要操作系统的支持,不同操作系统的支持是不一样的,不能很好的和java中线程优先级一一对应,因此,在设计多线程应用程序时,其功能的实现一点不能依赖于线程的优先级,而是把线程优先级作为一中提高程序效率的手段。

  2.线程休眠

复制代码
  @Override
            public void run() {
                int i=0;
                while(i++ < 5){
                    //线程t1等于2时休眠0.2秒
                    if(i == 2){
                        try{
                            Thread.sleep(200);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println(Thread.currentThread()+" "+i);
                }
            }
        },"t1");
复制代码

线程Thread提供了两种线程休眠的方法,sleep(long millis)和sleep(long millis ,int nanos)这两种方法都带有休眠时间参数,必须等待休眠时间结束,线程才会转换到就绪状态

 四、线程让步

 

复制代码
 Thread t2 = new Thread(()->{
            int i=0;
            while(i++ < 5){
                System.out.println(Thread.currentThread()+" "+i);
            }
        },"t2");
        Thread t3 = new Thread(()->{
            int i=0;
            while(i++ < 5){
                if(i == 2){
                    System.out.println("线程让步");
                    Thread.yield();//线程做出让步
                }
                System.out.println(Thread.currentThread()+" "+i);
            }
        },"t3");
        t2.start();
        t3.start();
复制代码

 

注意sleep集合yield方法有点类似,都可以让当前线程暂停,但是yield不会阻塞线程,他只是将线程转换成就绪状态,让调度器重新调度一次,由于JVM默认采用抢占式资源调度模型,所有线程都会再次抢占CPU资源使用权,所以在执行线程让步后并不能保证立即执行其他线程

五、线程插队

 

复制代码
Thread t4 = new Thread(new Runnable() {
            @Override
            public void run() {
                int i=0;
                while(i++ < 5){
                    System.out.println(Thread.currentThread().getName()+" "+i);
                }
            }
        },"t4");
        t4.start();
        for(int i = 1; i < 6; i++){
            System.out.println(Thread.currentThread().getName()+" "+i);
            if(i==2){
                t4.join();
            }
        }
复制代码

 

当线程插队优先执行时,整个程序执行完毕后才会执行其他线程。

 

posted @   panther125  阅读(58)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示