Java 线程详解(一)常用方法、线程优先级

版权声明:欢迎转载,转载请注明出处哦! https://blog.csdn.net/qq_41647999/article/details/87934356

目录直通车

一、 进入正题之前,先看“三连”

二、 线程例子

三、 多线程的创建与使用

四、 Thread方法总结

1、 start()

2、 run()

3、 currentThread()

4、 getName()

5、 setName()

6、 yield()

7、 Join()

8、 isAlive()

9、 Sleep(long x)

五、 线程的优先级

六、 多线程实例

1、 非匿名方式

2、 匿名方式


一、 进入正题之前,先看“三连”

什么是程序(Progress)?

使用某编程语言编写的,为了完成特定任务的静态的代码。

什么是进程(Program)

程序的一次执行过程,或者正在运行的一个程序(比如说正在运行的微信和网易云音乐)。动态过程:有它自身的产生、存在、消亡的过程。

什么是线程(Thread)

说白了,进程可以细分线程,所以进程一般是由很多线程组成的,是程序内部的一条执行路径。多线程就是在同一时间执行多个线程(同一个程序里面需要同时执行多个任务,比如说360可以同时体验和清理垃圾)。

二、 线程例子

在子线程里完成1-100的输出,主线程也执行相同操作。

public class TestThread {
    /**
     * 在子线程里完成1-100的输出,主线程也执行相同操作。
     */
    public static void main(String[] args) {
        SubThread st =new SubThread();
        /*
         * public void start()导致此线程开始执行; Java虚拟机调用此线程的run方法。
         * 结果是两个线程同时运行:当前线程(从调用返回到start方法)和另一个线程(执行其run方法)。
         * 不止一次启动线程是不合法的。 特别地,一旦线程 完成执行就可能不会重新启动。
         */
        st.start();
        for (int i = 1;i<101;i++){
           // Thread.currentThread().getName() 获取当前线程的名称
	 System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
}
class  SubThread extends Thread{
    /**
     * 重写Thread类run()方法,方法内完成子线程完成的事情
     */
    public void run(){
        for (int i = 1;i<101;i++){
	   System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
}

写到 st.start() 的时候,发现点出来的还有个 run() 的方法。问题:为什么使用的start来启动线程而不使用run,那么run与start有什么区别呢?接下来将start换成run启动一下,观察运行结果:

结果说明,子线程没有启动。

结论:不能通过Thread实现类对象的run()方法去启动一个线程。

三、 线程的创建与使用

          创建线程SubThread st2 =new SubThread(); 

          再次运行st2.start() 即使用。

public class TestThread {
    /**
     * 在子线程里完成1-100的输出,主线程也执行相同操作。
     */
    public static void main(String[] args) {
        SubThread st =new SubThread();
	SubThread st2 =new SubThread();

        /*
         * public void start()导致此线程开始执行; Java虚拟机调用此线程的run方法。
         * 结果是两个线程同时运行:当前线程(从调用返回到start方法)和另一个线程(执行其run方法)。
         * 不止一次启动线程是不合法的。 特别地,一旦线程 完成执行就可能不会重新启动。
         */
        st.start();
	st2.start();
        for (int i = 1;i<101;i++){
           // Thread.currentThread().getName() 获取当前线程的名称
	 System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
}
class  SubThread extends Thread{
    /**
     * 重写Thread类run()方法,方法内完成子线程完成的事情
     */
    public void run(){
        for (int i = 1;i<101;i++){
	   System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
}

四、 Thread方法总结

上述例子中有几个方法,已经或多或少都有了一定的理解。

1、 start()

启动线程并执行相应的run()方法

2、 run()

在使用类的继承之后,run方法是一定要重写的,所以在run里面运行子线程需要被   执行的代码。

3、 currentThread()

静态的,调用当前线程。

4、 getName()

获取当前线程的名字。

5、 setName()

设置当前线程的名字。

6、 yield()

调用子方法的线程释放当前CPU的执行权(举个例子,当前有一根棒棒糖,现在有子线程和主线程两个人去抢,谁抢到就是谁的),yield的用途:比如说一个线程执行到等待状态的时候,此时让其它的线程拿到CPU执行权。那么是否可以设置优先级呢?

下面实例,多运行几次,观察结果:

public class TestThread {
    /**
     * 在子线程里完成1-100的输出,主线程也执行相同操作。
     */
    public static void main(String[] args) {
        // 创建线程
        SubThread st =new SubThread();
        /*
         * public void start()导致此线程开始执行; Java虚拟机调用此线程的run方法。
         * 结果是两个线程同时运行:当前线程(从调用返回到start方法)和另一个线程(执行其run方法)。
         * 一个线程只能启动一次。 特别地,一旦线程 完成执行就可能不会重新启动。
         */
        st.setName("子线程:");
        Thread.currentThread().setName("主线程:");
        st.start();
        for (int i = 1;i<101;i++){
            System.out.println(Thread.currentThread().getName()+":"+i);
            if (i % 10 == 0){
                Thread.currentThread().yield();
            }
        }
    }
}
class  SubThread extends Thread{
    /**
     * 重写Thread类run()方法,方法内完成子线程完成的事情
     */
    public void run(){
        for (int i = 1;i<101;i++){
            // Thread.currentThread().getName() 获取当前线程的名称
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
}

7、 Join()

比如,在A线程中调用B线程中的join方法,则A停止执行,优先B执行,B执行完了以后在接着join()之后代码执行。类似于学生在排队打饭的时候,学生让老师来插队,老师打完饭之后,后面的人再接着打饭。

public class TestThread {
    /**
     * 在子线程里完成1-100的输出,主线程也执行相同操作。
     */
    public static void main(String[] args) {
        // 创建线程
        SubThread st =new SubThread();
        /*
         * public void start()导致此线程开始执行; Java虚拟机调用此线程的run方法。
         * 结果是两个线程同时运行:当前线程(从调用返回到start方法)和另一个线程(执行其run方法)。
         * 一个线程只能启动一次。 特别地,一旦线程 完成执行就可能不会重新启动。
         */
        st.setName("子线程:");
        Thread.currentThread().setName("主线程:");
        st.start();
        for (int i = 1;i<101;i++){
            System.out.println(Thread.currentThread().getName()+":"+i);
            if (i == 20){
               try{
                   st.join();
               }catch (InterruptedException e){
                   e.printStackTrace();
               }
            }
        }
    }
}
class  SubThread extends Thread{
    /**
     * 重写Thread类run()方法,方法内完成子线程完成的事情
     */
    public void run(){
        for (int i = 1;i<101;i++){
            // Thread.currentThread().getName() 获取当前线程的名称
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
}

运行效果:

8、 isAlive()

判断当前线程是否还存活。

9、 Sleep(long x)

显示的让当前线程睡眠x毫秒。

五、 线程的优先级

MAX_PRIORITY(10) 最大为10

MIN_PRIORITY(1) 最小为1

NORM_PRIORITY(5) 默认为5

方法:

getPriority():返回线程优先级。

setPriority(int newPriority) :改变线程的优先级。

线程创建时会继承父线程的优先级。

注意:优先级只增大抢到CPU执行权的概率,并不存在先执行和后执行的问题,优先级越大,抢到的概率越大。

例子:

public class TestThread {
    
    public static void main(String[] args) {
        // 创建线程
        SubThread st =new SubThread();
        /*
         * public void start()导致此线程开始执行; Java虚拟机调用此线程的run方法。
         * 结果是两个线程同时运行:当前线程(从调用返回到start方法)和另一个线程(执行其run方法)。
         * 一个线程只能启动一次。 特别地,一旦线程 完成执行就可能不会重新启动。
         */
        st.setName("子线程");
        /*
        设置线程的优先级
        设置为最大的优先级时,可以为10,也可以为Thread.MAX_PRIORITY
         */
        st.setPriority(Thread.MAX_PRIORITY);
        Thread.currentThread().setName("主线程");
        st.start();
        System.out.println(st.getName()+"的优先级为:"+st.getPriority());
        System.out.println(Thread.currentThread().getName()+"的优先级为:"+Thread.currentThread().getPriority());
        for (int i = 1;i<101;i++){
            System.out.println(Thread.currentThread().getName()+":"+i);

        }
    }
}
class  SubThread extends Thread{
    /**
     * 重写Thread类run()方法,方法内完成子线程完成的事情
     */
    public void run(){
        for (int i = 1;i<101;i++){
            // Thread.currentThread().getName() 获取当前线程的名称
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
}

六、 线程实例

创建两个子线程,分别输出0-100的奇数和偶数。

首先有两种方式实现:匿名和非匿名两种,匿名方式的代码更加简洁。

1、 非匿名方式

public class TestThread {
    public static void main(String[] args) {
        SubThread1 st1 = new SubThread1();
        SubThread2 st2 = new SubThread2();
        st1.start();
        st2.start();
    }
}
class  SubThread1 extends Thread{
    public void run(){
        for (int i=1;i<101;i++){
            if (i % 2 == 0){
                System.out.println(i);
            }
        }
    }
}
class  SubThread2 extends Thread{
    public void run(){
        for (int i=1;i<101;i++){
            if (i % 2 != 0){
                System.out.println(i);
            }
        }
    }
}

2、 匿名方式

public class TestThread {
    public static void main(String[] args) {
        new Thread(()->{
            for (int i=1;i<101;i++){
                if (i % 2 == 0){
                    System.out.println(i);
                }
            }
        }).start();
        new Thread(()->{
            for (int i=1;i<101;i++){
                if (i % 2 != 0){
                    System.out.println(i);
                }
            }
        }).start();
    }
}

猜你喜欢

转载自blog.csdn.net/qq_41647999/article/details/87934356