首页 > 编程语言 > 详细

Java基础之多线程

时间:2019-06-08 21:53:09      阅读:116      评论:0      收藏:0      [点我收藏+]

Java基础之多线程

记一次失败的学习方式

线程的三中创建方式,先上代码:

/*
    创建新线程的三种方式:
  1、继承Thread类;
  2、实现Runable接口;
  3、匿名内部类;

需求:创建多线程对象,开启多线程。在子线程中输出1-100之间的偶数,主线程输出1-100之间的奇数。
 */
public class Test9 {
    public static void main(String[] args) {
/*
        线程启动必须调用start()方法,而非run()
        //方式一
        ThreadTest1 tt1 = new ThreadTest1();
        tt1.setPriority(10);//设置线程优先级,默认为5,范围1-10
        tt1.start();
*/
/*
        //方式二
        ThreadTest2 tt2 = new ThreadTest2();
        Thread theTt2Thread = new Thread(tt2);
        theTt2Thread.start();
*/
        //方式三
        Thread tt3 = new Thread(){
            @Override
            public void run(){
                //使用匿名类可以很方便的访问外部变量(这里并未访问外部局部变量)
                //但是在JDK7以前,就必须使用final修饰
                for (int i = 0; i < 100; i++) {
                    if (i % 2 == 0) System.out.println("子线程:" + i);
                }
            }
        };
        //tt3.setPriority(10);//线程优先级太高导致子线程打印完主线程才打印┓(?′?`?)┏233333(主线程默认5)
        tt3.start();
        //同时,该匿名类可以使用lambda表达式简化
        Thread tt4 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                if (i % 2 == 0) System.out.println("子线程:" + i);
            }
        });

        //主线程打印奇数
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 1) System.out.println("主线程:" + i);
        }
    }
}

//通过继承Thread类来创建新线程
class ThreadTest1 extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 0) System.out.println("子线程:" + i);
        }
    }
}

//通过实现Runnable接口来创建新线程
class ThreadTest2 implements Runnable {
    public void run() {
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 0) System.out.println("子线程:" + i);
        }
    }
}

最开始执行该代码时,会产生这样的结果:
技术分享图片
子线程居然在主线程打印完了才开始打印,这曾一度让我以为没有创建出新线程,刚开始的时候start()方法在主方法下,我以为是顺序的原因,所以我先调用子线程的start()方法,然后在主方法打印(也就是现在的代码),发现结果还是这样,我甚至以为是因为ThreadTest方法不是公共的原因,然后想到之前看C#的时候有讲到优先级问题,然后百度了一下发现了具体原因:

结果居然变了
技术分享图片
子线程居然又开始工作了,我花了一晚上查线程优先级问题,最后发现最开始的情况居然复现不了了???(绝对不是主线程for循环在上面的原因)
不行我得把我查到的结论整理一下o(╥﹏╥)o,等以后再遇到这种情况再说吧

线程优先级

线程的状态,这里有一个很经典的线程状态图:

技术分享图片

新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread();
就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行;
运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就 绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;
阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才 有机会再次被CPU调用以进入到运行状态。根据阻塞产生的原因不同,阻塞状态又可以分为三种:

1.等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;
2.同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;
3.其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

参见这篇博客

1.在任意时刻,当有多个线程处于可运行状态时,运行系统总是挑选一个优先级最高的线程执行,只有当线程停止、退出或者由于某些原因不执行的时候,低优先级的线程才可能被执行
2.两个优先级相同的线程同时等待执行时,那么运行系统会以round-robin的方式选择一个线程执行(即轮询调度,以该算法所定的)(Java的优先级策略是抢占式调度!)
3.被选中的线程可因为一下原因退出,而给其他线程执行的机会:
  1) 一个更高优先级的线程处于可运行状态(Runnable)
  2)线程主动退出(yield),或它的run方法结束
  3)在支持分时方式的系统上,分配给该线程的时间片结束
4.Java运行系统的线程调度算法是抢占式(preemptive)的,当更高优先级的线程出现并处于Runnable状态时,运行系统将选择高优先级的线程执行
5.例外地,当高优先级的线程处于阻塞状态且CPU处于空闲时,低优先级的线程也会被调度执行

参见这里

最后放个很详细的博客,不过有些地方还不是特别明白,以后再仔细研读

Java基础之多线程

原文:https://www.cnblogs.com/lixin-link/p/10991710.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!