我是靠谱客的博主 苗条未来,最近开发中收集的这篇文章主要介绍线程(Thread)(代码)继承Thread类线程调度线程控制:实现Runnable接口,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

在了解线程之前,我们先看看线程与进程的区别

进程:是正在运行的程序

  • 是系统进行资源分配和调用的独立单位
  • 每一个进程都有它自己的内存空间和系统资源

线程:是进程中的单个顺序控制流,是一条执行路径

  • 单线程:一个进行如果只有一条执行路径,则称为单线程程序
  • 多线程:一个进程如果有多条执行路径,则称为多线程程序

比如:

一个微信客户端则是一个进程

如果你和一个妹纸视频,则是单线程

如果你同时传视频文件给多个妹子,则就是多线程

多线程的实现方式有2种:

  • 继承Thread类
  • 实现Runnable接口

继承Thread类

package com.Thread;

/**
 * @author 林高禄
 * @create 2020-05-14-10:21
 */
public class MyThread1 extends Thread {
    @Override
    public void run() {
        for(int i=0;i<5;i++){
            System.out.println(this.getName()+","+i);
        }
    }
}
package com.Thread;

/**
 * @author 林高禄
 * @create 2020-05-14-10:20
 */
public class ThreadDemo1 {
    public static void main(String[] args) {
        MyThread1 my1 = new MyThread1();
        MyThread1 my2 = new MyThread1();
        my1.run();
        my2.run();
    }
}

输出:

Thread-0,0
Thread-0,1
Thread-0,2
Thread-0,3
Thread-0,4
Thread-1,0
Thread-1,1
Thread-1,2
Thread-1,3
Thread-1,4

发现输出的结果是按顺序来的,并不是多线程,那时因为:

  • run():封装线程执行的代码,直接调用,相当于普通方法的调用
  • start():启动线程,然后有JVM调用此线程的run()方法

所以要调用start方法

package com.Thread;

/**
 * @author 林高禄
 * @create 2020-05-14-10:21
 */
public class MyThread1 extends Thread {
    public MyThread1() {
    }

    public MyThread1(String name) {
        super(name);
    }

    @Override
    public void run() {
        for(int i=0;i<100;i++){
            System.out.println(this.getName()+","+i);
        }
    }
}
package com.Thread;

/**
 * @author 林高禄
 * @create 2020-05-14-10:20
 */
public class ThreadDemo1 {
    public static void main(String[] args) {
        MyThread1 my1 = new MyThread1("第1个线程");
        MyThread1 my2 = new MyThread1("第2个线程");
        my1.start();
        System.out.println("当前线程名字"+Thread.currentThread().getName());
        my2.start();
    }
}

输出:

当前线程名字main
第2个线程,0
第2个线程,1
第1个线程,0
第1个线程,1
第1个线程,2
第2个线程,2
第2个线程,3
第1个线程,3
第1个线程,4

.....省略

多线程已经执行,并且是随机的,这个和线程调度有关

线程调度

线程有2种调度模型

  • 分时调度模型:所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间片
  • 抢占式调度模型:优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的CPU时间片相对多一些

Java使用的是抢占式调度模型

假如计算机只有一个CPU,那么CPU在某一个时刻只能执行一条指令,线程只有得到CPU时间片,也就是使用权才可以执行指令。所以说多线程程序的执行是有随机性,因为谁抢到CPU的使用权是不一定的。

Thread类中设置和获取线程优先级的方法:

  • public final int getPriority():返回此线程的优先级
  • public final void setPriority(int newPriority):更改此线程的优先级

Java中线程的优先级范围是1-10,默认优先级是5

package com.Thread;

/**
 * @author 林高禄
 * @create 2020-05-14-10:21
 */
public class MyThread1 extends Thread {
    public MyThread1() {
    }

    public MyThread1(String name) {
        super(name);
    }

    @Override
    public void run() {
        for(int i=0;i<5;i++){
            System.out.println(this.getName()+","+i);
        }
    }
}
package com.Thread;

/**
 * @author 林高禄
 * @create 2020-05-14-10:20
 */
public class ThreadDemo1 {
    public static void main(String[] args) {
        MyThread1 my1 = new MyThread1("第1个线程");
        MyThread1 my2 = new MyThread1("第2个线程");
        System.out.println("线程默认优先级"+Thread.NORM_PRIORITY);
        System.out.println("线程最小优先级"+Thread.MIN_PRIORITY);
        System.out.println("线程最大优先级"+Thread.MAX_PRIORITY);
        my1.setPriority(1);
        my2.setPriority(10);
        my1.start();
        my2.start();
    }
}

输出:

线程默认优先级5
线程最小优先级1
线程最大优先级10
第2个线程,0
第1个线程,0
第2个线程,1
第2个线程,2
第2个线程,3
第2个线程,4
第1个线程,1
第1个线程,2
第1个线程,3
第1个线程,4

线程控制:

  • static void sleep(long millis):使当前正在执行的线程停留(暂停执行)指定的毫秒数
  • void join():等待这个线程死亡
  • void setDaemon(boolean on):将此线程标记为守护线程,当运行的线程都是守护线程时,Java虚拟机将退出
package com.Thread;

/**
 * @author 林高禄
 * @create 2020-05-14-10:21
 */
public class MyThread1 extends Thread {
    public MyThread1() {
    }

    public MyThread1(String name) {
        super(name);
    }

    @Override
    public void run() {
        for(int i=0;i<5;i++){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(this.getName()+","+i);
        }
    }
}
package com.Thread;

/**
 * @author 林高禄
 * @create 2020-05-14-10:20
 */
public class ThreadDemo1 {
    public static void main(String[] args) throws Exception{
        MyThread1 my1 = new MyThread1("第1个线程");
        MyThread1 my2 = new MyThread1("第2个线程");
        my1.start();
        my2.start();
    }
}

输出:

第1个线程,0
第2个线程,0
第2个线程,1
第1个线程,1
第2个线程,2
第1个线程,2
第2个线程,3
第1个线程,3
第1个线程,4
第2个线程,4 

 结果是必然的,因为我们每执行一次,休眠一秒,这样有足够的时间让下一个线程争取CPU

我们再来看看void join():等待这个线程死亡

package com.Thread;

/**
 * @author 林高禄
 * @create 2020-05-14-10:21
 */
public class MyThread1 extends Thread {
    public MyThread1() {
    }

    public MyThread1(String name) {
        super(name);
    }

    @Override
    public void run() {
        for(int i=0;i<5;i++){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(this.getName()+","+i);
        }
    }
}
package com.Thread;

/**
 * @author 林高禄
 * @create 2020-05-14-10:20
 */
public class ThreadDemo1 {
    public static void main(String[] args) throws Exception{
        MyThread1 my1 = new MyThread1("第1个线程");
        MyThread1 my2 = new MyThread1("第2个线程");
        my1.start();
        my1.join();
        my2.start();
    }
}

输出:

第1个线程,0
第1个线程,1
第1个线程,2
第1个线程,3
第1个线程,4
第2个线程,0
第2个线程,1
第2个线程,2
第2个线程,3
第2个线程,4

即使我们每执行一次,休眠一秒,这样有足够的时间让下一个线程争取CPU,但是我们调用了my1.join();也就是要等my1线程死亡了,my2才调用。

接着看void setDaemon(boolean on):将此线程标记为守护线程,当运行的线程都是守护线程时,Java虚拟机将退出。

我们把代码调整下,让MyThread1重写的run()方法循环500次,然后其实例都设置为守护线程

package com.Thread;

/**
 * @author 林高禄
 * @create 2020-05-14-10:21
 */
public class MyThread1 extends Thread {
    public MyThread1() {
    }

    public MyThread1(String name) {
        super(name);
    }

    @Override
    public void run() {
        for(int i=0;i<500;i++){
            System.out.println(this.getName()+","+i);
        }
    }
}
package com.Thread;

/**
 * @author 林高禄
 * @create 2020-05-14-10:20
 */
public class ThreadDemo1 {
    public static void main(String[] args) {
        MyThread1 my1 = new MyThread1("第1个线程");
        MyThread1 my2 = new MyThread1("第2个线程");
        Thread.currentThread().setName("主线程");
        my1.setDaemon(true);
        my2.setDaemon(true);
        my1.start();
        my2.start();
        for(int i =0;i<10;i++){
            System.out.println(Thread.currentThread().getName()+","+i);
        }
    }
}

输出:

主线程,0
主线程,1
主线程,2
主线程,3
主线程,4
第2个线程,0
第1个线程,0
第1个线程,1
第1个线程,2
第1个线程,3
第1个线程,4
第2个线程,1
主线程,5
主线程,6
主线程,7
主线程,8
主线程,9
第2个线程,2
第2个线程,3
第2个线程,4
第2个线程,5

从结果可以看出,当主线程执行完后,守护线程会挂掉,但是并不是立即挂掉,而是很快就挂掉。

实现Runnable接口

package com.Thread;

/**
 * @author 林高禄
 * @create 2020-05-14-10:21
 */
public class MyThread2 implements Runnable {
    public MyThread2() {
    }

    @Override
    public void run() {
        for(int i=0;i<5;i++){
            System.out.println(Thread.currentThread().getName()+","+i);
        }
    }
}
package com.Thread;

/**
 * @author 林高禄
 * @create 2020-05-14-10:20
 */
public class ThreadDemo2 {
    public static void main(String[] args) {
        MyThread2 my1 = new MyThread2();
        Thread t1 =  new Thread(my1,"第1个线程");
        Thread t2 =  new Thread(my1,"第2个线程");
        t1.start();
        t2.start();
    }
}

实现Runnable接口,其调用方式也不一样

  • Thread(Runnable target)
  • Thread(Runnable target, String name)

 

最后

以上就是苗条未来为你收集整理的线程(Thread)(代码)继承Thread类线程调度线程控制:实现Runnable接口的全部内容,希望文章能够帮你解决线程(Thread)(代码)继承Thread类线程调度线程控制:实现Runnable接口所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(64)

评论列表共有 0 条评论

立即
投稿
返回
顶部